初探.NET多線程
也許是自己天性愚鈍吧,看了兩天的文章,也還沒有很好的solution,不過對於Multithreading倒是有了一點小小的認識,謹記於此。首先是使用多線程的重要性了。這點其實不必多言,大家都會知道把佔用大量CPU週期的數據處理放到GUI Thread中,造成GUI無法響應用戶的操作是一種十分糟糕的做法。爲了實現更好的用戶體驗,就應該創建新的進程來處理持續時間較長的操作,通常我們會把負責非UI操作的進程稱爲Worker Thread(工作進程)。重要性說完了,讓我們關注到更具體的多線程實現上來。
在.NET中進行多線程開發,會有很多選擇,其中最常見的就是使用Control.Invoke方法了。Invoke方法提供了一種在Worker Thread調用GUI Thread中delegate的途徑。同時結合Control.InvokeRequired的屬性,我們也可以輕易地判斷某個線程是否爲創建該Control的線程。爲了對Invoke方法有更深入的認識,我仔細地閱讀了CodeProject上《Worker Threads In C#》一文[1]。在文中有這樣的代碼:
這裏給出了Invoke方法的一種使用方式,但是可惜的是,我並不能對其使用的必要性有充分的理解。因爲我把這段代碼改爲m_form.AddString(s),並且將AddString方法的access modifier由private改爲public,程序仍然是運行好好的。那麼Invoke方法的意義在於什麼呢?而MSDN給Invoke方法下的定義又是如此的簡單:Executes the specified delegate on the thread that owns the control's underlying window handle. 真的是看不明白了,煩請各位朋友不吝賜教。
問題雖然有,但是認識還得接着說。多線程開發很重要的一點就是線程間的通信問題,在CodeProject的這篇文章中,Worker Thread與GUI Thread是通過ManualResetEvent來實現的。我們從文中的代碼:
if ( m_EventStop.WaitOne(0, true) ) {
m_EventStopped.Set();
return;
}
// GUI Thread
if ( m_WorkerThread != null && m_WorkerThread.IsAlive ) {
m_EventStopThread.Set();
while (m_WorkerThread.IsAlive) {
if ( WaitHandle.WaitAll((new ManualResetEvent[] {m_EventThreadStopped}), 100,true) ) {
break;
}
Application.DoEvents();
}
}
可以看到Worker Thread與GUI Thread之間的通信過程:
1、當Worker Thread處於活動狀態,而GUI Thread通過設置m_EventStopThread的狀態向Worker Thread發出Signal,並使自己進入循環等待狀態,直至接收到由Worker Thread發出的Signal;
2、Worker Thread在接收到該Signal之後採取相應的操作,例子中的操作就是通過設置m_EventStopped的狀態向GUI Thread發出自己已經停止的Signal並且返回;
3、GUI Thread接收到來自Worker Thread發出的Signal後,跳出循環;
呼,終於說完了。由於自己剛剛開始接觸C#的MultiThreading開發,疏漏一定不少。請各位路過的朋友不要錯過扔磚頭的機會哦,^_^
[1] 小新0574爲這篇不錯的文章提供了譯文,有興趣的朋友可以參考一下中文版。