关键词搜索

源码搜索 ×
×

C# WinForm多线程开发(二) ThreadPool 与 Timer

发布2014-04-15浏览3139次

详情内容

原文地址:点击打开链接

[摘要]本文介绍C# WinForm多线程开发之ThreadPool 与 Timer,并提供详细的示例代码供参考。

本文接上文,继续探讨WinForm中的多线程问题,再次主要探讨threadpool 和timer。

一 、ThreadPool

线程池(ThreadPool)是一种相对较简单的方法,它适应于一些需要多个线程而又较短任务(如一些常处于阻塞状态的线程),它的缺点是对创建的线程不能加以控制,也不能设置其优先级。由于每个进程只有一个线程池,当然每个应用程序域也只有一个线程池(对线),所以你将发现 ThreadPool类的成员函数都为static!当你首次调用ThreadPool.QueueUserWorkItem、 ThreadPool.RegisterWaitForSingleObject等,便会创建线程池实例。下面我就线程池当中的两函数作一介绍:

  1. public static bool QueueUserWorkItem( //调用成功则返回true
  2. WaitCallback callBack,//要创建的线程调用的委托
  3. object state //传递给委托的参数
  4. )//它的另一个重载函数类似,只是委托不带参数而已
    此函数的作用是把要创建的线程排队到线程池,当线程池的可用线程数不为零时(线程池有创建线程数的限制,缺身值为25),便创建此线程,否则就排队到线程池等到它有可用的线程时才创建。

  1. public static RegisteredWaitHandle RegisterWaitForSingleObject(
  2. WaitHandle waitObject,// 要注册的 WaitHandle
  3. WaitOrTimerCallback callBack,// 线程调用的委托
  4. object state,//传递给委托的参数
  5. int TimeOut,//超时,单位为毫秒,
  6. bool executeOnlyOnce //是否只执行一次
  7. );
  8. public delegate void WaitOrTimerCallback(
  9. object state,//也即传递给委托的参数
  10. bool timedOut//true表示由于超时调用,反之则因为waitObject
  11. );

此函数的作用是创建一个等待线程,一旦调用此函数便创建此线程,在参数waitObject变为终止状态或所设定的时间TimeOut到了之前,它都处于 “阻塞”状态,值得注意的一点是此“阻塞”与Thread的WaitSleepJoin状态有很大的不同:当某Thread处于 WaitSleepJoin状态时CPU会定期的唤醒它以轮询更新状态信息,然后再次进入WaitSleepJoin状态,线程的切换可是很费资源的;而用此函数创建的线程则不同,在触发它运行之前,CPU不会切换到此线程,它既不占用CPU的时间又不浪费线程切换时间,但CPU又如何知道何时运行它?实际上线程池会生成一些辅助线程用来监视这些触发条件,一旦达到条件便启动相应的线程,当然这些辅助线程本身也占用时间,但是如果你需创建较多的等待线程时,使用线程池的优势就越加明显。

更详细内容demo:

  1. namespace TestMethodInvoker
  2. {
  3. public partial class Form2 : Form
  4. {
  5. public Form2()
  6. {
  7. InitializeComponent();
  8. }
  9. private void button1_Click(object sender, EventArgs e)
  10. {
  11. //ThreadPool.RegisterWaitForSingleObject(
  12. // ev,
  13. // new WaitOrTimerCallback(WaitThreadFunc),
  14. // 4,
  15. // 2000,
  16. // false//表示每次完成等待操作后都重置计时器,直到注销等待
  17. // );
  18. ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), "test1");
  19. //Thread.Sleep(10000);
  20. }
  21. private delegate void MyInvokeDelegate(string name);
  22. private void Test(object o)
  23. {
  24. richTextBox1.Text += string.Format("the object is {0} \n", o);
  25. }
  26. public void ThreadFunc(object b)
  27. {
  28. this.Invoke(new MyInvokeDelegate(Test), b);
  29. }
  30. public void WaitThreadFunc(object b, bool t)
  31. {
  32. richTextBox1.Text += string.Format("the object is {0},t is {1}\n", b, t);
  33. }
  34. }
  35. }
     一个很值得扩展的地方时,这里的invoke 用的是代理,其实还有其他的方法,比如 action 和func。实例代码如下:

  1. this.Invoke(new Action<string>(this.ChangeText), o.ToString());
  2. this.Invoke(new Action(delegate() { this.textBox1.Text = o.ToString();}));
  3. private void DoSomething(object o)
  4. {
  5. System.Func<string, int> f = new Func<string, int>(this.GetId);
  6. object result = this.Invoke(f, o.ToString());
  7. MessageBox.Show(result.ToString());
  8. }
  9. private int GetId(string name)
  10. {
  11. this.textBox1.Text = name;
  12. if (name == "Y")
  13. {
  14. return 999;
  15. }
  16. else
  17. {
  18. return 0;
  19. }
  20. }

二、 Timer

它适用于需周期性调用的方法,它不在创建计时器的线程中运行,它在由系统自动分配的单独线程中运行。这和Win32中的SetTimer方法类似。它的构造为:

  1. public Timer(
  2. TimerCallback callback,//所需调用的方法
  3. object state,//传递给callback的参数
  4. int dueTime,//多久后开始调用callback
  5. int period//调用此方法的时间间隔
  6. );//

如果 dueTime 为0,则 callback 立即执行它的首次调用。如果 dueTime 为 Infinite,则 callback 不调用它的方法。计时器被禁用,但使用 Change 方法可以重新启用它。如果 period 为0或 Infinite,并且 dueTime 不为 Infinite,则 callback 调用它的方法一次。计时器的定期行为被禁用,但使用 Change 方法可以重新启用它。如果 period 为零 (0) 或 Infinite,并且 dueTime 不为 Infinite,则 callback 调用它的方法一次。计时器的定期行为被禁用,但使用 Change 方法可以重新启用它。 

在创建计时器之后若想改变它的period和dueTime,我们可以通过调用Timer的Change方法来改变:

  1. public bool Change(
  2. int dueTime,
  3. int period
  4. );//
    显然所改变的两个参数对应于Timer中的两参数。

相关技术文章

最新源码

下载排行榜

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载