5.使用线程池
在所有的多线程解决方案中,ThreadPool应该是你最常用的技术。使用线程池的好处是明显的:1,它是易于控制的,而且功能也很强大,有助于降低多线程编程的整体代价;2,在线程池中一个线程不会由于任务的结束而灭绝,而是将继续执行其他任务,从而可以大大减少线程创建和销毁的开销。线程池提供了一个重要方法—QueueUserWorkItem。借助于此方法,能够把任何任务推入一个后台线程中,然后在后台队列中执行相应的功能。同时,它的创建也相当简单。
事实上,你会发现在执行相同任务的情况下,与上述方法并不存在太大的差别。
清单9:
private void Button_Click(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((s) =>
{
this.Dispatcher.BeginInvoke(() =>
{
int minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
this.TextBox1.Text = String.Format("WorkerThreads = {0} ~ {1}, CompletionPortThreads = {2} ~ {3}",
minWorkerThreads, maxWorkerThreads, minCompletionPortThreads, maxCompletionPortThreads);
});
});
}
{
ThreadPool.QueueUserWorkItem((s) =>
{
this.Dispatcher.BeginInvoke(() =>
{
int minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
this.TextBox1.Text = String.Format("WorkerThreads = {0} ~ {1}, CompletionPortThreads = {2} ~ {3}",
minWorkerThreads, maxWorkerThreads, minCompletionPortThreads, maxCompletionPortThreads);
});
});
}
下面,让我们更仔细地探讨一下线程池的使用。在下面的代码中,我们要创建两个示例:一是仍然涉及到方法QueueUserWorkItem,另一个涉及到方法RegisterWaitForSingleObject。
首先,让我们把两个TextBlock控件放在ThreadPoolTestPage.xaml示例页面上。如下所示:
清单10:
<StackPanel HorizontalAlignment="Left" Margin="5,5,0,5" Grid.Row="1" Width="623">
<TextBlock x:Name="txtMsgQueueUserWorkItem" Text="Click here to start thread 1"
MouseLeftButtonDown="txtMsgQueueUserWorkItem_MouseLeftButtonDown" Margin="30" />
<TextBlock x:Name="txtRegisterWaitForSingleObject" Text="Click here to start thread 2"
MouseLeftButtonDown="txtRegisterWaitForSingleObject_MouseLeftButtonDown" Margin="30" />
</StackPanel>
<TextBlock x:Name="txtMsgQueueUserWorkItem" Text="Click here to start thread 1"
MouseLeftButtonDown="txtMsgQueueUserWorkItem_MouseLeftButtonDown" Margin="30" />
<TextBlock x:Name="txtRegisterWaitForSingleObject" Text="Click here to start thread 2"
MouseLeftButtonDown="txtRegisterWaitForSingleObject_MouseLeftButtonDown" Margin="30" />
</StackPanel>
当点击上述任意两个标签之一,相应的程序过程将被启动。下面,让我们继续跟踪观察在后台代码中发生的情况:
清单11:
//省略其他内容……
using System.Threading;
namespace SilverlightMultiThread
{
public partial class ThreadPoolTestPage : Page
{
using System.Threading;
namespace SilverlightMultiThread
{
public partial class ThreadPoolTestPage : Page
{