线程池
线程池功能应用程序可以有多个线程,这些线程在休眠状态中需要耗费大量时间来等待事件发生。其他线程可能进入睡眠状态,并且仅定期被唤醒以轮循更改或更新状态信息,然后再次进入休眠状态。为了简化对这些线程的管理,.NET框架为每个进程提供了一个线程池,一个线程池有若干个等待操作状态,当一个等待操作完成时,线程池中的辅助线程会执行回调函数。线程池中的线程由系统管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙.如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值.超过最大值的线程可以排队,但他们要等到其他线程完成后才启动
什么情况下不要使用线程池●如果需要使一个任务具有特定优先级
●如果具有可能会长时间运行(并因此阻塞其他任务)的任务
●如果需要将线程放置到单线程单元中(线程池中的线程均处于多线程单元中)
●如果需要永久标识来标识和控制线程,比如想使用专用线程来终止该线程,将其挂起或按名称发现它
System.ThreadingPool类实现了线程池,这是一个静态类,它提供了管理线程的一系列方法
Threading.QueueUserItem方法在线程池中创建一个线程池线程来执行指定方法(用委托WaitCallBack表示),并将该线程排入线程池的队列等待执行。
publc static Boolean QueueUserWorkItem(WaitCallback wc,Object state);
传递参数调用QueueUserWorkItem时传入的Object类型参数传递到任务过程,可以通过这种方式来向任务过程传递参数。如果任务过程需要多个参数,可以定义包含这些数据的类,并将其强制转换为Object数据类型
线程池示例// ThreadPool.cs
// 线程池示例
using System;
using System.Threading;
public class Test
{
// 存放要计算的数值的字段
static double number1 = -1;
static double number2 = -1;
public static void Main()
{
// 获取线程池的最大线程数和维护的最小空闲线程数
int maxThreadNum, portThreadNum;
int minThreadNum;
ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);
ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
Console.WriteLine("最大线程数:", maxThreadNum);
Console.WriteLine("最小空闲线程数:", minThreadNum);
// 函数变量值
int x = 15600;
// 启动第一个任务:计算x的8次方
Console.WriteLine("启动第一个任务:计算的8次方。", x);
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc1), x);
// 启动第二个任务:计算x的8次方根
Console.WriteLine("启动第二个任务:计算的8次方根。", x);
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc2), x);
// 等待,直到两个数值都完成计算
while (number1 == -1 || number2 == -1) ;
// 打印计算结果
Console.WriteLine("y() = ", x, number1 + number2);
}
// 启动第一个任务:计算x的8次方
static void TaskProc1(object o)
{
number1 = Math.Pow(Convert.ToDouble(o), 8);
}
// 启动第二个任务:计算x的8次方根
static void TaskProc2(object o)
{
number2 = Math.Pow(Convert.ToDouble(o), 1.0 / 8.0);
}
}
线程池结构
[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] public static class ThreadPool {
[Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated. Please use ThreadPool.BindHandle(SafeHandle) instead.", false), SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static bool BindHandle(IntPtr osHandle) { return BindIOCompletionCallbackNative(osHandle); } [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static bool BindHandle(SafeHandle osHandle) { if (osHandle == null) { throw new ArgumentNullException("osHandle"); } bool flag = false; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { osHandle.DangerousAddRef(ref success); flag = BindIOCompletionCallbackNative(osHandle.DangerousGetHandle()); } finally { if (success) { osHandle.DangerousRelease(); } } return flag; } [MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool BindIOCompletionCallbackNative(IntPtr fileHandle); public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads) { GetAvailableThreadsNative(out workerThreads, out completionPortThreads); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads); public static void GetMaxThreads(out int workerThreads, out int completionPortThreads) { GetMaxThreadsNative(out workerThreads, out completionPortThreads); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads); public static void GetMinThreads(out int workerThreads, out int completionPortThreads) { GetMinThreadsNative(out workerThreads, out completionPortThreads); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads); [MethodImpl(MethodImplOptions.InternalCall)] private static extern unsafe bool PostQueuedCompletionStatus(NativeOverlapped* overlapped); public static bool QueueUserWorkItem(WaitCallback callBack) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack, null, ref lookForMyCaller, true); } public static bool QueueUserWorkItem(WaitCallback callBack, object state) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack, state, ref lookForMyCaller, true); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool QueueUserWorkItem(object state, ref StackCrawlMark stackMark, bool compressStack); private static bool QueueUserWorkItemHelper(WaitCallback callBack, object state, ref StackCrawlMark stackMark, bool compressStack) { if (callBack == null) { throw new ArgumentNullException("WaitCallback"); } _ThreadPoolWaitCallback callback = new _ThreadPoolWaitCallback(callBack, state, compressStack, ref stackMark); state = callback; return QueueUserWorkItem(state, ref stackMark, compressStack); } public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) { if (millisecondsTimeOutInterval < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, true); } public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) { if (millisecondsTimeOutInterval < -1L) { throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, true); } public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce) { long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1L) { throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } if (totalMilliseconds > 0x7fffffffL) { throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)totalMilliseconds, executeOnlyOnce, ref lookForMyCaller, true); } [CLSCompliant(false)] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, true); } private static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce, ref StackCrawlMark stackMark, bool compressStack) { if (RemotingServices.IsTransparentProxy(waitObject)) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); } RegisteredWaitHandle registeredWaitHandle = new RegisteredWaitHandle(); if (callBack == null) { throw new ArgumentNullException("WaitOrTimerCallback"); } _ThreadPoolWaitOrTimerCallback callback = new _ThreadPoolWaitOrTimerCallback(callBack, state, compressStack, ref stackMark); state = callback; registeredWaitHandle.SetWaitObject(waitObject); IntPtr handle = RegisterWaitForSingleObjectNative(waitObject, state, millisecondsTimeOutInterval, executeOnlyOnce, registeredWaitHandle, ref stackMark, compressStack); registeredWaitHandle.SetHandle(handle); return registeredWaitHandle; } [MethodImpl(MethodImplOptions.InternalCall)] private static extern IntPtr RegisterWaitForSingleObjectNative(WaitHandle waitHandle, object state, uint timeOutInterval, bool executeOnlyOnce, RegisteredWaitHandle registeredWaitHandle, ref StackCrawlMark stackMark, bool compressStack); [SecurityPermission(SecurityAction.Demand, ControlThread = true)] public static bool SetMaxThreads(int workerThreads, int completionPortThreads) { return SetMaxThreadsNative(workerThreads, completionPortThreads); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads); [SecurityPermission(SecurityAction.Demand, ControlThread = true)] public static bool SetMinThreads(int workerThreads, int completionPortThreads) { return SetMinThreadsNative(workerThreads, completionPortThreads); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads); [CLSCompliant(false), SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static unsafe bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) { return PostQueuedCompletionStatus(overlapped); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object state) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack, state, ref lookForMyCaller, false); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) { if (millisecondsTimeOutInterval < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, false); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object state) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack, state, ref lookForMyCaller, false); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) { if (millisecondsTimeOutInterval < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, false); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) { if (millisecondsTimeOutInterval < -1L) { throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, false); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce) { long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1L) { throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } if (totalMilliseconds > 0x7fffffffL) { throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)totalMilliseconds, executeOnlyOnce, ref lookForMyCaller, false); } [CLSCompliant(false), SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject, callBack, state, millisecondsTimeOutInterval, executeOnlyOnce, ref lookForMyCaller, false); } }