一、线程概述:【引用MSDN】
通常,WPF 应用程序从两个线程开始:一个用于处理呈现,一个用于管理 UI。呈现线程有效地隐藏在后台运行,而 UI 线程则接收输入、处理事件、绘制屏幕以及运行应用程序代码。大多数应用程序都使用一个 UI 线程,但在某些情况下,最好使用多个线程。我们将在后面举例说明这一点。
Dispatcher 都只能在一个线程中执行工作项。
输入与响应之间的任何可察觉的延迟都会使用户不快。
Dispatcher 队列中的工作项。当大型操作完成时,可以将结果报告给 UI 线程来显示。
一直以来,Windows 只允许创建 UI 元素的线程访问这些元素。这意味着负责某项长时间运行任务的后台线程无法更新已完成的文本框。Windows 这样做是为了确保 UI 组件的完整性。如果列表框的内容在绘制过程中被后台线程更新,那么该列表框看上去将会很奇怪。
DispatcherObject 的方法的开头调用。
BeginInvoke 是异步的,将立即返回。
DispatcherPriority 级别的详细信息可以在 Windows SDK 文档中找到。
二、下面是线程的一个小例子
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Center" >
<Button Content="StartWithThread"
Click="StartOrStop"
Name="startStopButton"
Margin="5,0,5,0"
/>
<TextBlock Margin="10,5,0,0">Biggest Prime Found:</TextBlock>
<TextBlock Name="bigPrime" Margin="4,5,0,0">3</TextBlock>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" >
<Button Content="MessageBox.show"
Name="startStopButton2"
Margin="5,0,5,0" Click="startStopButton2_Click" />
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal" VerticalAlignment="Center" >
<Button Content="StartWithoutThread"
Name="startStopButton3"
Margin="5,0,5,0" Click="startStopButton3_Click" />
<TextBlock Margin="10,5,0,0">data:</TextBlock>
<TextBlock Name="myData" Margin="4,5,0,0">3</TextBlock>
</StackPanel>
</Grid>
后台代码:
/// <summary>
/// Interaction logic for ThreadTest.xaml
/// </summary>
public partial class ThreadTest : Window
{
public delegate void NextPrimeDelegate();
//Current number to check
private long num = 3;
private bool continueCalculating = false;
public ThreadTest()
{
InitializeComponent();
}
private void StartOrStop(object sender, RoutedEventArgs e)
{
if (continueCalculating)
{
continueCalculating = false;
startStopButton.Content = "Resume";
}
else
{
continueCalculating = true;
startStopButton.Content = "Stop";
startStopButton.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new NextPrimeDelegate(CheckNextNumber));
}
}
public void CheckNextNumber()
{
// Reset flag.
NotAPrime = false;
for (long i = 3; i <= Math.Sqrt(num); i++)
{
if (num % i == 0)
{
// Set not a prime flag to true.
NotAPrime = true;
break;
}
}
// If a prime number.
if (!NotAPrime)
{
bigPrime.Text = num.ToString();
}
num += 2;
if (continueCalculating)
{
startStopButton.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.SystemIdle,
new NextPrimeDelegate(this.CheckNextNumber));
}
}
private bool NotAPrime = false;
private void startStopButton2_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello Thread");
}
private void startStopButton3_Click(object sender, RoutedEventArgs e)
{
long n = 0;
// If a prime number.
while (n < 10000000)
{
myData.Text = n.ToString();
n++;
}
}
}
效果图1:当运行"Stop"按钮时,在单击“MessageBox.show"按钮,则能弹出窗口HelloThead。
效果图2。当单击“StartWithoutThrad"按钮时,此时再单击“MessageBox.show"按钮,则提示Not Responding。因为此时没有用到线程。
参考资料:http://msdn.microsoft.com/zh-cn/library/ms741870.aspx#threading_overview
三、 下面是使用线程的三种方式
原文:http://www.cnblogs.com/iupme/archive/2011/05/18/2049949.html
第1种用 Task类. 推荐用这个办法
{
Dispatcher x = Dispatcher.CurrentDispatcher;//取得当前工作线程
//另开线程工作
Task<int> 计数 = new Task<int>(() => { return 计数方法(); });
计数.ContinueWith(工作完毕后方法);//工作完毕后执行的方法
计数.Start();//开始工作
}
public void工作完毕后方法(Task<int> 参数)
{
if (参数.IsCompleted) //正常工作完毕
{
var 结果 = 参数.Result; //取得结果
//处理结果.
//本方法非界面线程.如果需要在界面线程操作,需要转移到界面线程
}
}
int c;
public int 计数方法()
{
return c++;
}
第2种方法用线程.
{
Dispatcher x = Dispatcher.CurrentDispatcher;//取得当前工作线程
//另开线程工作
System.Threading.ThreadStart start = delegate()
{
//工作函数
Func<string> fu = new Func<string>(() => { return ""; });//工作函数
var 工作结果 = fu();//开始工作
//异步更新界面
x.BeginInvoke(new Action(() =>
{
//在界面线程操作 可以使用 工作结果
}), DispatcherPriority.Normal);
};
new System.Threading.Thread(start).Start(); //启动线程
}
第3种方法用 BackgroundWorker.
这种方法介绍的比较多了.就不说了.
public void线程初始化()
{
后台线程 = new BackgroundWorker();
后台线程.WorkerSupportsCancellation = true; //可以取消
后台线程.DoWork += new DoWorkEventHandler(后台线程_DoWork);
后台线程.RunWorkerCompleted += new RunWorkerCompletedEventHandler(后台线程_RunWorkerCompleted);
}
public void 启动后台线程()
{
后台线程.RunWorkerAsync();
}
void 后台线程_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//工作完毕的方法
}
void 后台线程_DoWork(object sender, DoWorkEventArgs e)
{
//工作方法
}
通常,WPF 应用程序从两个线程开始:一个用于处理呈现,一个用于管理 UI。呈现线程有效地隐藏在后台运行,而 UI 线程则接收输入、处理事件、绘制屏幕以及运行应用程序代码。大多数应用程序都使用一个 UI 线程,但在某些情况下,最好使用多个线程。我们将在后面举例说明这一点。
Dispatcher 都只能在一个线程中执行工作项。
输入与响应之间的任何可察觉的延迟都会使用户不快。
Dispatcher 队列中的工作项。当大型操作完成时,可以将结果报告给 UI 线程来显示。
一直以来,Windows 只允许创建 UI 元素的线程访问这些元素。这意味着负责某项长时间运行任务的后台线程无法更新已完成的文本框。Windows 这样做是为了确保 UI 组件的完整性。如果列表框的内容在绘制过程中被后台线程更新,那么该列表框看上去将会很奇怪。
DispatcherObject 的方法的开头调用。
BeginInvoke 是异步的,将立即返回。
DispatcherPriority 级别的详细信息可以在 Windows SDK 文档中找到。
第1种用 Task类. 推荐用这个办法
{
Dispatcher x = Dispatcher.CurrentDispatcher;//取得当前工作线程
//另开线程工作
Task<int> 计数 = new Task<int>(() => { return 计数方法(); });
计数.ContinueWith(工作完毕后方法);//工作完毕后执行的方法
计数.Start();//开始工作
}
public void工作完毕后方法(Task<int> 参数)
{
if (参数.IsCompleted) //正常工作完毕
{
var 结果 = 参数.Result; //取得结果
//处理结果.
//本方法非界面线程.如果需要在界面线程操作,需要转移到界面线程
}
}
int c;
public int 计数方法()
{
return c++;
}
第2种方法用线程.
{
Dispatcher x = Dispatcher.CurrentDispatcher;//取得当前工作线程
//另开线程工作
System.Threading.ThreadStart start = delegate()
{
//工作函数
Func<string> fu = new Func<string>(() => { return ""; });//工作函数
var 工作结果 = fu();//开始工作
//异步更新界面
x.BeginInvoke(new Action(() =>
{
//在界面线程操作 可以使用 工作结果
}), DispatcherPriority.Normal);
};
new System.Threading.Thread(start).Start(); //启动线程
}
第3种方法用 BackgroundWorker.
这种方法介绍的比较多了.就不说了.
public void线程初始化()
{
后台线程 = new BackgroundWorker();
后台线程.WorkerSupportsCancellation = true; //可以取消
后台线程.DoWork += new DoWorkEventHandler(后台线程_DoWork);
后台线程.RunWorkerCompleted += new RunWorkerCompletedEventHandler(后台线程_RunWorkerCompleted);
}
public void 启动后台线程()
{
后台线程.RunWorkerAsync();
}
void 后台线程_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//工作完毕的方法
}
void 后台线程_DoWork(object sender, DoWorkEventArgs e)
{
//工作方法
}