實戰.Net多執行緒(一)

草上爬發表於2008-08-07
編寫桌面程式的時候當遇到長時間的方法呼叫時,大家都會遇到主執行緒被掛起、介面無響應的狀況。執行緒操作是解決類似問題的絕佳手段,但對於剛接觸執行緒的朋友來講編寫和除錯多執行緒程式是非常痛苦的,尤其是在VC的MFC下,沒有一定的C++基礎,很難做出專業的多執行緒程式來。

幸好,.Net框架為我們提供了非常簡便的方法和機制來建立多執行緒程式,譬如:Thread、執行緒池、非同步方法呼叫以及BackgroundWorker!Thread和BackgroundWorker在MSDN中關於這兩個類都有非常詳細的解釋以及豐富的示例,在後續的文章裡我們會利用非常實際的示例程式來進行實戰。在這裡我們首先討論非同步方法呼叫。

所謂非同步方法呼叫英文即為Asynchronous Method Invocation,討論非同步方法呼叫實際上就是討論如何以非阻塞的方式來呼叫方法。常規的阻塞式方法呼叫例如:

        //呼叫同一個耗時的方法
        private void a()
        {
            Thread.Sleep(10000);
        }

        //阻塞式呼叫
        private void button1_Click(object sender, EventArgs e)
        {
            a();
            MessageBox.Show("button1_Click will return!");
        }

當單擊button1後,主介面立即失去響應,持續10s後會顯示一個訊息框報告button1_Click方法將要返回,這時a()方法已經呼叫結束並返回。這表明主執行緒是在按照button1_click->a()->button1_click的順序依次執行程式碼,所有程式碼都在主執行緒中執行。

然後,我們在窗體上放置第二個button,即button2,來演示如何進行非同步方法呼叫。.Net2.0提供了兩種途徑實現非同步方法呼叫,每種途徑實際上都是使用委託來實現。一種是簡單的無引數傳遞的MethodInvoker委託型別,另一種是標準的delegate型別。MethodInvoker型別的委託不接受任何引數傳遞,而delegate型別的委託使用起來則相當靈活,並且可以傳遞任意型別的引數。我們主要以MethodInvoker為例,首先看一下button2_Click事件的內容:

        //非同步方法呼叫  by MethodInvoker
        private MethodInvoker simpleDelegate1;

        private void button2_Click(object sender, EventArgs e)
        {
            simpleDelegate1 = new MethodInvoker(a);
            simpleDelegate1.BeginInvoke(null, null);
            MessageBox.Show("button2_Click will return!");
        }

當單擊button2後,會立即顯示一個訊息框報告button1_Click方法將要返回,而主介面沒有失去響應。這表明在主執行緒下的button2_click要返回了!而這時的a()方法正在另一個獨立的執行緒上繼續執行著,而且在執行的10s過程中,我們仍然可以隨意拖動窗體、改變窗體大小、繼續單擊窗體上的按鈕甚至關閉窗體。這種呼叫即稱為非同步方法呼叫。

使用c++的朋友都知道函式指標,其實.Net下的委託就是一個函式指標型別,在.Net下已經沒有函式的概念了,所以也稱為方法指標,只不過框架把一些東西隱藏了,我們不必關心細節,不必用指標的方式顯示宣告罷了。其實委託也可以同步阻塞的方式執行,你可以嘗試將button2_Click中的程式碼:

       simpleDelegate1.BeginInvoke(null, null);
更改為:
       simpleDelegate1.Invoke();

其執行方式與button1_Click完全一樣。

Invoke以同步方式開始執行委託,其引數必須與要執行的方法完全一致。BeginInvoke就是以非同步方式開始執行委託,它與您需要執行的方法具有相同的引數,另外還有兩個可選引數。在.Net下當你看到以Begin開頭的方法時幾乎都是以非同步方式執行程式碼。而對應BeginInvoke的就是EndInvoke方法,EndInvoke的任務就是傳遞BeginInvoke的返回值,我們將在下一篇博文中詳細介紹BeginInvoke和EndInvoke的使用,以及如何捕獲非同步方法呼叫的結束。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14325734/viewspace-421452/,如需轉載,請註明出處,否則將追究法律責任。

相關文章