代码改变世界

WPF调用线程(三)线程池初步

2011-04-05 23:47  杨延成  阅读(4279)  评论(0编辑  收藏  举报

当我们频繁的要调用线程来执行任务时,一个好的办法是采用线程池来对线程进行管理,
 “线程池”是可以用来在后台执行多个任务的线程集合。 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会占用主线程,也不会延迟后续请求的处理。一旦池中的某个线程完成任务,它将返回到等待线程队列中,等待被再次使用。 这使应用程序可以避免为每个任务创建新线程的开销。线程还是比较昂贵的。

(you must avoid using threads as much as  possible because they consume a lot of memory and they require time to create, destroy,and manage . Time is also wasted when Windows context switches between threads and when garbage collections occur . However, this discussion should also help you realize that threads must be used sometimes because they allow Windows to be robust and responsive)摘自 CLR via C#


线程池通常具有最大线程数限制。 如果所有线程都繁忙,则额外的任务将放入队列中,直到有线程可用时才能够得到处理。

下面用WPF程序演示线程池基本的使用,运行效果如图:

XAML代码如下:

View Code
<Window x:Class="WpfThreadTest.ThreadPoolDemo"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
Title
="ThreadPoolDemo" Height="165" Width="611">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="116*" />
<ColumnDefinition Width="473*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Content="启动线程1" Name="button1" Margin="20 10" Click="button1_Click" />
<Button Content="启动线程2" Grid.Row="1" Name="button2" Margin="20 10" Click="button2_Click" />
<TextBlock Grid.Column="1" Grid.Row="1" Name="textBlock1" Text="TextBlock" Margin="20 10" />
<TextBlock Name="textBlock2" Text="TextBlock" Grid.Column="1" Margin="20 10" />
<Button Content="活动线程数" Grid.Row="2" Name="button3" Margin="20 10" Click="button3_Click" />
<TextBlock Grid.Column="1" Grid.Row="2" Name="textBlock3" Text="TextBlock" Margin="20 10" />
</Grid>
</Window>

后台CS代码:

1 namespace WpfThreadTest
2 {
3 /// <summary>
4 /// ThreadPoolDemo.xaml 的交互逻辑
5 /// </summary>
6 public partial class ThreadPoolDemo : Window
7 {
8 public ThreadPoolDemo()
9 {
10 InitializeComponent();
11 ///设置线程池的最大可用辅助线程数目,最大异步线程数目
12 ThreadPool.SetMaxThreads(100, 10);
13
14 }
15
16 private void button1_Click(object sender, RoutedEventArgs e)
17 {
18 //调用线程去计算数字,仅供演示
19 ThreadPool.QueueUserWorkItem(new WaitCallback(CountNumber), 1);
20 }
21 private void CountNumber(object state)
22 {
23 int count = int.Parse(state.ToString());
24 while (true)
25 {
26 count++;
27 this.textBlock2.Dispatcher.Invoke(
28 DispatcherPriority.Normal,
29 new Action(() =>
30 {
31 this.textBlock2.Text = count.ToString();
32 }));
33 Thread.Sleep(100);
34 }
35 }
36 /// <summary>
37 /// 测试线程中传递引用对象,以期望获得返回值
38 /// </summary>
39 /// <param name="state"></param>
40 private void ReturnValueMethod(object state)
41 {
42 MyParam myParam = state as MyParam;
43 myParam.MyInt = 100;
44 myParam.MyString = "updated string";
45 }
46
47 private void button2_Click(object sender, RoutedEventArgs e)
48 {
49 ///将引用对象传递给线程
50 MyParam myParam = new MyParam() { MyInt = 12, MyString = "test" };
51
52 ThreadPool.QueueUserWorkItem(new WaitCallback(ReturnValueMethod), myParam);
53
54 ///主线程睡眠5ms后,再去读取对象的值
55 ///如果不睡眠,直接读取,可能读不到修改后的值,因为他们处于不同的线程当中
56 ///当主线程去读取时,子线程尚未更改,
57 ///即便如此,也会有读取不到的时候,故此种传值方式并不十分可取,
58 ///具体线程返回值可以参考MSDN http://msdn.microsoft.com/zh-cn/library/wkays279.aspx
59 Thread.Sleep(5);
60 this.textBlock1.Text=string.Format("MyInt:{0},MyString:{1}", myParam.MyInt, myParam.MyString);
61 }
62
63 private void button3_Click(object sender, RoutedEventArgs e)
64 {
65 ThreadPool.QueueUserWorkItem(new WaitCallback(GetThreadPoolInfo), null);
66 }
67 private void GetThreadPoolInfo(object state)
68 {
69 while (true)
70 {
71 int workerThreads = 0;
72 int completionPortThreads = 0;
73 ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
74 this.textBlock3.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() =>
75 {
76 this.textBlock3.Text =
77 string.Format("池中可用辅助线程:{0},可用异步 I/O 线程:{1}",
78 workerThreads, completionPortThreads);
79 }));
80 Thread.Sleep(1000);
81 }
82 }
83 }
84 public class MyParam
85 {
86 public int MyInt { get; set; }
87 public string MyString { get; set; }
88 }
89 }