>>返回《C# 併發編程》html
解決三個需求編程
開發人員常常建立一個新線程來執行單個任務,當任務完成時,該線程就會死亡。多線程
DLL_THREAD_ATTACH
通知,從而致使磁盤中的pages被轉移到內存中以便代碼能夠執行DLL_THREAD_DETACH
通知,該線程的堆棧內存被釋放,而且內核對象被釋放(若是其使用計數變爲0線程池執行任務流程併發
線程池提供了四種功能:異步
要爲線程池中的任務排隊,請使用 System.Threading
命名空間中定義的 ThreadPool
靜態類。異步編程
要使線程池線程異步調用方法,您的代碼必須調用 ThreadPool
的 QueueUserWorkItem
方法,以下所示:函數
public static Boolean QueueUserWorkItem(WaitCallback wc, Object state); public static Boolean QueueUserWorkItem(WaitCallback wc);
這些方法將「工做項」(和可選的狀態數據)排隊到線程池中的線程,而後當即返回。性能
System.Threading.WaitCallback
委託類型定義以下:spa
public delegate void WaitCallback(Object state);
Object
類型的數據,做爲參數傳遞給「工做項」委託
QueueUserWorkItem
版本將 null
傳遞給WaitCallback
方法CLR的線程池將在必要時自動建立線程,並在可能的狀況下重用現有線程。該線程在處理回調方法後不會當即被銷燬。它返回線程池,以便準備處理隊列中的任何其餘工做項。線程
線程池調用異步方法
using System; using System.Threading; class App { static void Main() { Console.WriteLine("Main thread: 列入一個異步操做."); ThreadPool.QueueUserWorkItem(new WaitCallback(MyAsyncOperation)); Console.WriteLine("Main thread: 執行其餘操做."); // ... Console.WriteLine("Main thread: 暫停在這,以模擬執行其餘操做。"); Console.ReadLine(); } static void MyAsyncOperation(Object state) { Console.WriteLine("ThreadPool thread: 執行異步操做."); // ... Thread.Sleep(5000); // 等待5s,模擬執行工做項 // 方法返回,致使線程掛起自身,以等待其餘「工做項」 } }
輸出爲:
Main thread: 列入一個異步操做. Main thread: 執行其餘操做. Main thread: 暫停在這,以模擬執行其餘操做。 ThreadPool thread: 執行異步操做.
System.Threading
命名空間定義了 Timer
類。當構造 Timer
類的實例時,您在告訴線程池您但願在未來的特定時間回調您的方法。 Timer
類提供了四個構造函數:
public Timer(TimerCallback callback, Object state, Int32 dueTime, Int32 period); public Timer(TimerCallback callback, Object state, UInt32 dueTime, UInt32 period); public Timer(TimerCallback callback, Object state, Int64 dueTime, Int64 period); public Timer(TimerCallback callback, Object state, Timespan dueTime, TimeSpan period);
System.Threading.TimerCallback
委託類型定義以下:
public delegate void TimerCallback(Object state);
state
做爲參數傳遞dueTime
參數爲 0dueTime
參數爲 Timeout.Infinite
或 0
period
容許您指定每一個連續調用以前等待的時間(以毫秒爲單位)
Timer
對象後,線程池自動監視時間
Change
和 Dispose
方法cs public Boolean Change(Int32 dueTime, Int32 period); public Boolean Change(UInt32 dueTime, UInt32 period); public Boolean Change(Int64 dueTime, Int64 period); public Boolean Change(TimeSpan dueTime, TimeSpan period); public Boolean Dispose(); public Boolean Dispose(WaitHandle notifyObject);
Change
方法使您能夠更改 Timer對象 的 dueTime
和 period
Dispose
方法能夠徹底和有選擇的取消回調
每2000毫秒(或2秒)調用一次方法示例:
using System; using System.Threading; class App { static void Main() { Console.WriteLine("每2秒檢查一次修改狀態."); Console.WriteLine(" (按 Enter 鍵中止示例程序)"); Timer timer = new Timer(new TimerCallback(CheckStatus), null, 0, 2000); Console.ReadLine(); } static void CheckStatus(Object state) { Console.WriteLine("檢查狀態."); // ... } }
輸出爲:
每2秒檢查一次修改狀態. (按 Enter 鍵中止示例程序) 檢查狀態. 檢查狀態. 檢查狀態. ... ...
在進行性能研究時,Microsoft研究人員發現許多應用程序生成線程,只是爲了等待單個內核對象接收發出的信號。
對象發出信號後,線程將某種通知發佈到另外一個線程,而後返回回來以等待對象再次發出信號。
一些開發人員甚至編寫了其中多個線程各自等待一個對象的代碼。這是對系統資源的極大浪費。
所以,若是您的應用程序中當前有等待單個內核對象發出信號的線程,那麼線程池再次是您提升應用程序性能的理想資源。
System.Threading.ThreadPool
類中定義的一些靜態方法(RegisterWaitForSingleObject
)。要使線程池線程在發出內核對象信號時調用方法
public static RegisterWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, WaitOrTimerCallback callback, Object state, UInt32 milliseconds, Boolean executeOnlyOnce); public static RegisterWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, WaitOrTimerCallback callback, Object state, Int32 milliseconds, Boolean executeOnlyOnce); public static RegisterWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, WaitOrTimerCallback callback, Object state, TimeSpan milliseconds, Boolean executeOnlyOnce); public static RegisterWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, WaitOrTimerCallback callback, Object state, Int64 milliseconds, Boolean executeOnlyOnce);
當您調用RegisterWaitForSingleObject
方法時
waitObject
參數,須要線程池等待的內核對象
callback
參數,須要線程池線程調用的方法
System.Threading.WaitOrTimerCallback
委託類型定義:
public delegate void WaitOrTimerCallback(Object state, Boolean timedOut);
state
參數, callback
委託對象運行時須要的 state
參數
null
milliseconds
參數, 單位:毫秒,須要線程池等待多久後向內核對象發出超時信號
executeOnlyOnce
參數
true
,則線程池線程將僅執行一次回調方法,以後線程將再也不在 waitObject
參數上等待false
,則每次向內核對象發出信號時,線程池線程都會執行回調方法(這對於AutoResetEvent對象最有用)
waitObject
取消註冊調用WaitOrTimerCallback
委託類型的回調方法,bool
類型的 timedOut
參數值:
false
,說明內核對象收到信號,致使該方法被調用true
,說明在指定的時間內沒有發信號通知內核對象,超時後致使該方法被調用
RegisterWaitForSingleObject
方法返回一個 RegisteredWaitHandle
對象WaitHandle
,則您的應用程序能夠調用 RegisteredWaitHandle
的 Unregister
方法:cs public Boolean Unregister(WaitHandle waitObject);
waitObject
參數,指示當全部排隊的工做項均已執行時,如何通知您
null
WaitHandle
的對象引用傳遞給Unregister
方法,當已註冊的WaitHandle
的全部待處理工做項均已執行時,線程池將向該對象;。;(waitObject
)發出信號using System; using System.Threading; class App { static void Main() { AutoResetEvent are = new AutoResetEvent(false); RegisteredWaitHandle rwh = ThreadPool.RegisterWaitForSingleObject( are, new WaitOrTimerCallback(EventSignalled), null, 1100, false); for (Int32 x = 0 ; x < 5; x++) { Thread.Sleep(1000); are.Set(); } Thread.Sleep(2400); rwh.Unregister(null); Console.WriteLine("按 Enter 鍵中止示例程序"); Console.ReadLine(); } static void EventSignalled(Object state, Boolean timedOut) { if (timedOut) { Console.WriteLine("等待 AutoResetEvent 操做超時."); } else { Console.WriteLine("AutoResetEvent 接到信號."); } } }
輸出爲:
; 五次 AutoResetEvent 發送信號 AutoResetEvent 接到信號. AutoResetEvent 接到信號. AutoResetEvent 接到信號. AutoResetEvent 接到信號. AutoResetEvent 接到信號. ; 等待2.4s致使兩次超時 等待 AutoResetEvent 操做超時. 等待 AutoResetEvent 操做超時. ; 註銷後不在調用委託 按 Enter 鍵中止示例程序
關於線程池相關的 API 不須要熟練掌握,可是咱們瞭解了線程池的設計初衷和具有的功能,爲咱們更好的理解 異步編程、並行、多線程 有很大的助益。
前一章咱們瞭解了 同步上下文 是如何編排線程執行代碼的,這一章咱們瞭解了線程池,加深了異步任務交給線程池執行的理解,後面咱們開始對 異步編程、數據流塊、Rx等咱們經常使用的技術進行講解。