c#线程学习笔记二---线程池
线程池:ThreadPool:提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。
MSDN参考:http://msdn.microsoft.com/zh-cn/library/system.threading.threadpool.aspx
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 线程池1 { class Program { static void Main(string[] args) { WaitCallback wcb = new WaitCallback(myprocess);//声明一个WaitCallBack委托对象,用于将要执行的方法添加至线程池 for (int i = 0; i < 10;i++ ) { ThreadPool.QueueUserWorkItem(wcb, i);//依次将委托对象添加至线程池 } Console.WriteLine("开始执行"); } static void myprocess(object para)//声明一个和WaitCallback同样签名的方法 { Console.WriteLine("线程执行:{0}",para.ToString()); } } }
许多应用程序创建的线程都要在休眠状态中消耗大量时间,以等待事件发生。 其他线程可能进入休眠状态,只被定期唤醒以轮询更改或更新状态信息。 线程池通过为应用程序提供一个由系统管理的辅助线程池,使您可以更为有效地使用线程。
利用线程池,可以由系统来有效管理线程的调度和使用。
由于线程池的方法为静态方法,所以直接以ThreadPool.方法名()来调用
为了能使要执行的方法添加至线程队列,这里需要声明一个WaitCallback委托,所要添加的方法也要符合该委托的签名
MSDN-WaitCallback参考:http://msdn.microsoft.com/zh-cn/library/system.threading.waitcallback.aspx
public delegate void WaitCallback(Object state)
声明完委托对象后,将该委托添加至线程池中,运用ThreadPool.QueueUserWorkItem 方法 (WaitCallback, Object)
msdn-QueueUserWorkItem :http://msdn.microsoft.com/zh-cn/library/kbf0f1ct.aspx
ThreadPool.QueueUserWorkItem(WaitCallback callBack);
ThreadPool.QueueUserWorkItem(WaitCallback callBack,Object obj);
当遇到方法需要有参数传入调用时,可以通过该方法的重载来传入~
当添加完毕后,会由主线程自动调用线程池来进行执行,结果如下图
利用ManualResetEvent来控制线程事件的发生
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 线程池2 { class Program { static void Main(string[] args) { const int num = 5; ManualResetEvent[] MREs = new ManualResetEvent[num];//声明手动重置事件对象队列 myclass[] mcs = new myclass[num]; Console.WriteLine("开始执行{0}个线程",num); for (int i=0; i < num; i++) { MREs[i] = new ManualResetEvent(false);//初始化事件对象为无信号状态(非终止) mcs[i] = new myclass(MREs[i], i+1);//以事件对象队列元素来初始化myclass对象队列 ThreadPool.QueueUserWorkItem(mcs[i].myWaitCallback, i+1);//将myclass对象的处理方法添加至线程池 } WaitHandle.WaitAll(MREs);//这里主线程用WaitHandle.WaitAll(事件队列),目的是让主线程收到来自所有子线程执行完毕的信号后在向下继续执行 Console.WriteLine("全部执行完毕"); foreach (myclass mc in mcs) { Console.WriteLine("结果为:{0}",mc.RESULT); } } } class myclass { ManualResetEvent MRevent; Int64 result; int ThreadNum; public Int64 RESULT { get { return result; } } public myclass(ManualResetEvent mre,int tnum)//构造函数 { result = 1; MRevent = mre; ThreadNum = tnum; } public void myWaitCallback(object obj)//声明一个符合WaitCallback委托的方法 { Console.WriteLine("线程{0}执行中",ThreadNum); for (long temp = Convert.ToInt64(obj); temp > 0; temp--) { result = result * temp; } Console.WriteLine("线程{0}执行完毕", ThreadNum); MRevent.Set();//方法执行结束前,设置事件对象的信号发出(终止状态) } } }
ManualResetEvent类,继承于 System.Threading.EventWaitHandle<--System.Threading.WaitHandle,作用是通知一个或多个正在等待的线程已发生事件。利用其Wait....()方法可以使得当心线程处于阻止等待的状态,当收到信号后再继续运行。
这里设置了一个ManualResetEvent类的对象队列,让每一个要执行线程的myclass对象获得一个ManualResetEvent事件对象,并在主线程设置一个【WaitHandle.WaitAll(事件队列)】方法,目的是当所有子线程执行结束调用【ManualResetEvent事件对象.Set()】发出信号时,主线程的WaitHandle通过WaitAll的方法接受到所有子线程发出的信号后,主线程才方可执行
执行结果为
可以看到由于是系统线程池来管理子线程的运行,所以不是安照顺序来运行的~