[择要]本文引见C# WinForm多线程开辟之ThreadPool 与 Timer,并供应细致的示例代码供参考。
本文接上文,继承讨论WinForm中的多线程题目,再次重要讨论threadpool 和timer。
一 、ThreadPool
线程池(ThreadPool)是一种相对较简朴的要领,它适应于一些须要多个线程而又较短使命(如一些常处于壅塞状况的线程),它的瑕玷是对建立的线程不能加以掌握,也不能设置其优先级。由于每一个历程只要一个线程池,固然每一个应用程序域也只要一个线程池(对线),所以你将发明 ThreadPool类的成员函数都为static!当你初次挪用ThreadPool.QueueUserWorkItem、 ThreadPool.RegisterWaitForSingleObject等,便会建立线程池实例。下面我就线程池当中的两函数作一引见:
public static bool QueueUserWorkItem( //挪用胜利则返回true WaitCallback callBack,//要建立的线程挪用的托付 object state //传递给托付的参数 )//它的另一个重载函数相似,只是托付不带参数罢了
此函数的作用是把要建立的线程列队到线程池,当线程池的可用线程数不为零时(线程池有建立线程数的限定,缺身值为25),便建立此线程,不然就列队到线程池比及它有可用的线程时才建立。
public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject,// 要注册的 WaitHandle WaitOrTimerCallback callBack,// 线程挪用的托付 object state,//传递给托付的参数 int TimeOut,//超时,单元为毫秒, bool executeOnlyOnce //是不是只实行一次 ); public delegate void WaitOrTimerCallback( object state,//也即传递给托付的参数 bool timedOut//true示意由于超时挪用,反之则由于waitObject );
此函数的作用是建立一个守候线程,一旦挪用此函数便建立此线程,在参数waitObject变成停止状况或所设定的时候TimeOut到了之前,它都处于 “壅塞”状况,值得注意的一点是此“壅塞”与Thread的WaitSleepJoin状况有很大的差别:当某Thread处于 WaitSleepJoin状况时CPU会按期的叫醒它以轮询更新状况信息,然后再次进入WaitSleepJoin状况,线程的切换然则很费资本的;而用此函数建立的线程则差别,在触发它运转之前,CPU不会切换到此线程,它既不占用CPU的时候又不糟蹋线程切换时候,但CPU又怎样晓得什么时候运转它?实际上线程池会生成一些辅佐线程用来看管这些触发前提,一旦到达前提便启动响应的线程,固然这些辅佐线程自身也占用时候,然则假如你需建立较多的守候线程时,运用线程池的上风就越加显著。
更细致内容demo:
namespace TestMethodInvoker { public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //ThreadPool.RegisterWaitForSingleObject( // ev, // new WaitOrTimerCallback(WaitThreadFunc), // 4, // 2000, // false//示意每次完成守候操纵后都重置计时器,直到注销守候 // ); ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), "test1"); //Thread.Sleep(10000); } private delegate void MyInvokeDelegate(string name); private void Test(object o) { richTextBox1.Text += string.Format("the object is {0} \n", o); } public void ThreadFunc(object b) { this.Invoke(new MyInvokeDelegate(Test), b); } public void WaitThreadFunc(object b, bool t) { richTextBox1.Text += string.Format("the object is {0},t is {1}\n", b, t); } } }
一个很值得扩大的地方时,这里的invoke 用的是代办,实在另有其他的要领,比方 action 和func。实例代码以下:
this.Invoke(new Action<string>(this.ChangeText), o.ToString()); this.Invoke(new Action(delegate() { this.textBox1.Text = o.ToString();})); private void DoSomething(object o) { System.Func<string, int> f = new Func<string, int>(this.GetId); object result = this.Invoke(f, o.ToString()); MessageBox.Show(result.ToString()); } private int GetId(string name) { this.textBox1.Text = name; if (name == "Y") { return 999; } else { return 0; } }
二、 Timer
它适用于需周期性挪用的要领,它不在建立计时器的线程中运转,它在由体系自动分派的零丁线程中运转。这和Win32中的SetTimer要领相似。它的组织为:
public Timer( TimerCallback callback,//所需挪用的要领 object state,//传递给callback的参数 int dueTime,//多久后最先挪用callback int period//挪用此要领的时候距离 );//
假如 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要领来转变:
public bool Change( int dueTime, int period );//
明显所转变的两个参数对应于Timer中的两参数。
以上就是C# WinForm多线程开辟(二) ThreadPool 与 Timer的内容,更多相关内容请关注ki4网(www.ki4.cn)!