时间:2022-11-12 10:11:54 | 栏目:.NET代码 | 点击:次
提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。
创建线程需要时间。如果有不同的小任务要完成,就可以事先创建许多线程/在应完成这些任务时发出请求。不需要自己创建这样一个列表。该列表由ThreadPool类托管。
这个类会在需要时增减池中线程的线程数,直到最大的线程数。池中的最大线程数是可配置的。在双核CPU中,默认设置为1023 个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,以及线程池 中可用的最大线程数。
如果有更多的作业要处理,线程池中线程的个数也达到了极限,最新的作业就要排队,且必须等待线程完成其任务。
线程池使用起来很简单,但它有一些限制:
使用线程池线程的操作的情况包括:
GetAvailableThreads(Int32, Int32)
GetMaxThreads(Int32, Int32)
SetMaxThreads(Int32, Int32)
GetMinThreads(Int32, Int32)
SetMinThreads(Int32, Int32)
QueueUserWorkItem(WaitCallback, Object)
RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int32, Boolean)
int i = 0; int j = 0; //前面是辅助(也就是所谓的工作者)线程,后面是I/O线程 ThreadPool.GetMaxThreads(out i, out j); Console.WriteLine(i.ToString() + " " + j.ToString()); //默认都是1000 //获取空闲线程,由于现在没有使用异步线程,所以为空 ThreadPool.GetAvailableThreads(out i, out j); Console.WriteLine(i.ToString() + " " + j.ToString()); //默认都是1000
将方法排入队列以便执行,并指定包含该方法所用数据的对象。 此方法在有线程池线程变得可用时执行。
public static bool QueueUserWorkItem (System.Threading.WaitCallback callBack, object state);
实例:
static void Main(string[] args) { Person p = new Person(1, "刘备"); //启动工作者线程 ThreadPool.QueueUserWorkItem(new WaitCallback(RunWorkerThread), p); } static void RunWorkerThread(object obj) { Thread.Sleep(200); Console.WriteLine("线程池线程开始!"); Person p = obj as Person; Console.WriteLine(p.Name); } public class Person { public Person(int id, string name) { Id = id; Name = name; } public int Id { get; set; } public string Name { get; set; } }
注册一个等待 WaitHandle 的委托,并指定一个数来表示超时值(以毫秒为单位)。
将指定的方法排队到线程池,当超时或者等待委托接收到信号时,辅助线程将执行此方法,即主线程控制辅助线程什么时候开始执行。
public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject (System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce);
参数
waitObject
callBack
state
millisecondsTimeOutInterval
executeOnlyOnce
返回
RegisteredWaitHandle
// TaskInfo contains data that will be passed to the callback method. public class TaskInfo { public RegisteredWaitHandle Handle = null; public string OtherInfo = "default"; } public static void Main(string[] args) { // 主线程使用AutoResetEvent来给已注册的等待句柄发信号, 此等待句柄执行回调方法 AutoResetEvent ev = new AutoResetEvent(false); TaskInfo ti = new TaskInfo(); ti.OtherInfo = "First task"; // The TaskInfo for the task includes the registered wait handle returned by RegisterWaitForSingleObject. This // allows the wait to be terminated when the object has been signaled once (see WaitProc). ti.Handle = ThreadPool.RegisterWaitForSingleObject( ev, new WaitOrTimerCallback(WaitProc), ti, 1000, false ); // 主线程等待三秒,为了演示队列中的线程超时,然后发信号. Thread.Sleep(3100); Console.WriteLine("Main thread signals."); ev.Set();//发信号 // The main thread sleeps, which should give the callback method time to execute. If you comment out this line, the program usually ends before the ThreadPool thread can execute. Thread.Sleep(1000); // If you start a thread yourself, you can wait for it to end by calling Thread.Join. This option is not available with thread pool threads. } //The callback method executes when the registered wait times out, //or when the WaitHandle (in this case AutoResetEvent) is signaled. //WaitProc unregisters the WaitHandle the first time the event is signaled. public static void WaitProc(object state, bool timedOut) { TaskInfo ti = (TaskInfo)state; string cause = "TIMED OUT"; if (!timedOut) //如果Timeout为false,表示接收到的信号后执行的 { cause = "SIGNALED"; //如果回调方法执行的话是因为WaitHandle触发信号的话,则用反注册等待句柄来取消回调方法将来的执行。 if (ti.Handle != null) ti.Handle.Unregister(null);// } Console.WriteLine("WaitProc( {0} ) executes on thread {1}; cause = {2}.", ti.OtherInfo, Thread.CurrentThread.GetHashCode().ToString(), cause);//超时后执行的 }
结果如下:
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
WaitProc( First task ) executes on thread 7; cause = TIMED OUT.
Main thread signals.
WaitProc( First task ) executes on thread 7; cause = SIGNALED.