在這部分,我們將查看ThreadPool 類的多個方面並學習如何在我們的.NET 應用程序中使用ThreadPool 類的內容創建線程池。ThreadPool 類提供的線程可以用來做以下事情:
1. 處理工作組件
2. 處理異步I/O 調用
3. 處理定時器
4. 等待其他線程
下表給出了ThreadPool 類中的方法以及對應的功能。
上表中的QueueUserWorkItems() 和 RegisterWaitForSingleObject() 方法在線程池中起了非常重要的作用。我們將深入研究每個方法。現在看一下這兩個方法的語法和一個用C# 寫的小例子:
BindHandle() 方法綁定一個操作系統句柄到線程池上,通過這種方式可以調用BindIoCompletionCallback; BCL 中的幾個類 - 比如Socket 和 FileStream – 內部使用這個方法來將它們的句柄綁定到一個由CLR 創建的線程池的I/O完全端口上去。客戶端應用程序通常不需要直接調用這個方法,當BeginRead 或者 BeginReceive 方法被調用的時候系統會間接調用它們。
[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); }
osHandle 指向一個保存操作系統句柄的IntPtr 類型的值。函數的返回值是Boolean, true 表示已經綁定到句柄。如果調用方沒有足夠的權限的話,那么這個函數會拋出一個SecurityException.
GetAvailableThread() 方法獲取在到達線程池隊列最大限制之前仍然可以添加到線程池隊列中的請求數量:
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads) { GetAvailableThreadsNative(out workerThreads, out completionPortThreads); }
workThreads 表示線程池中工作線程的數量而completionPortThreads 表示異步I/O 線程的數量。
GetMaxThreads() 方法獲取一個線程池可以處理的最大並發請求數量。超過這個限制的任何請求都會被放入隊列中直到線程池中的一些線程被釋放以后它們才會被隊列中取出執行:
public static void GetMaxThreads(out int workerThreads, out int completionPortThreads) { GetMaxThreadsNative(out workerThreads, out completionPortThreads); }
workThreads 表示線程池中的工作線程數量而completionPortThread表示異步I/O 線程的數量。
QueueUserWorkItem() 是一個用來將一個工作組件放入線程池中的重載方法。它可能被以下面的兩種形式之一調用。第一種是這個方法將工作組件放入到線程池的隊列中並調用與其關聯的特定委托。這種情況下的語法如下:
[MethodImpl(MethodImplOptions.NoInlining)] public static bool QueueUserWorkItem(WaitCallback callBack) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack, null, ref lookForMyCaller, true); }
這里callBack 引用一個在線程池中的線程關聯到工作組件后調用的委托對象。返回值如果是true 表示方法成功,反之失敗。
第二種情況是這個方法將特定工作組件放到線程池的隊列中,並調用特定委托,當工作組件在線程池中執行時還要確定傳遞給委托的對象。這種情況下方法有如下語法:
[MethodImpl(MethodImplOptions.NoInlining)] public static bool QueueUserWorkItem(WaitCallback callBack, object state) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack, state, ref lookForMyCaller, true); }
callBack 引用一個當線程池中的線程執行工作組件以后調用的委托對象,state 引用當工作組件開始執行時傳遞給委托的狀態對象。返回值是true 表示方法執行成功,反之失敗。
RegisterWaitSingleObject() 也是一個重載方法。它注冊一個等待WaitHandle 的委托。這個類封裝了等待顯式訪問共享資源的操作系統對象。
這個方法采用以下四種形式之一。第一個形式,方法注冊一個委托並等待WaitHandle 被超時(毫秒級, Int32)事件觸發. 這種形式的重載方法有如下C# 語法:
[MethodImpl(MethodImplOptions.NoInlining)] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce);
在上面的語法中,waitObject 引用WaitHandle對象,callBack 引用將要被調用的WaitOrTimerCallback 委托。state 參數引用傳遞給委托的對象。millisecondsTimeOutInterval 參數引用超時對象;如果值是0那么函數會測試對象的狀態並立即返回,如果值是-1 函數會無限等待。executeOnlyOnce 參數表示線程在委托被調用之后是否繼續等待。RegisterWaitHandle 參數封裝了原生句柄。
如果millsecondsTimeOutInterval 參數小於-1 這個方法會拋出ArgumentOutOfRangeException.
第二種形式,方法與第一種方法的情況做的事情相同除了等待WaitHandle的時間參數類型為無符號Int32. 方法的重載形式如下:
[MethodImpl(MethodImplOptions.NoInlining)] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce);
第三種形式,等待WaitHandle 的方法的超時時間由TimeSpan確定。方法的重載形式如下:
[MethodImpl(MethodImplOptions.NoInlining)] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce);
第四種形式,超時時間類型由一個無符號整數類型值確定,由於無符號整型類型不屬於公共類型系統,所以這個方法不與CLS兼容:
[MethodImpl(MethodImplOptions.NoInlining), CLSCompliant(false)] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce);
UnsafeQueueUserWorkItem() 方法是QueueUserWorkItem() 方法的非安全版本。它不向工作線程傳播調用堆棧所以它不是安全的,這意味着代碼會丟失調用堆棧,這樣的話獲取安全權限就不可能了。它的語法如下:
public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object state);
UnsafeRegisterWaitForSingleObject() 方法是RegisterWaitForSingleObject() 方法的非安全版本,它有如下四種形式:
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce);
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce);
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce);
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce);
當從你不完全信任的代碼執行工作組件時不應該使用這些不安全代碼,一般不應該使用。
下一篇介紹 在C# 中使用線程池進行編程…