.Net多線程與Windows Forms編程筆記

來源:互聯網
上載者:User

多線程Winform編程會帶來的常見問題

1 UI線程執行耗時操作  UI線程被阻塞 無法響應表單訊息佇列中的其他訊息。

2 非UI線程修改UI屬性 由於表單資源也屬於臨界資源 所以有互斥訪問的機制。

3 線程的同步問題 線程A等待線程B執行完畢後才能開始執行。

問題1的解決方案:
解決方案只有一種,就是開啟新線程執行耗時操作,使原介面線程仍能夠響應表單訊息佇列中的使用者訊息及系統訊息。

開啟新線程的方式有以下各種:
1) 使用System.Threading.Thread類與System.Threading.ThreadStart委託或System.Threading.ParameterizedThreadStart委託來實現開啟新線程。
ThreadStart委託的類型: void ThreadStart(void);
ParameterizedThreadStart委託的類型: void ParameterizedThreadStart(object[]);

ThreadStart委託可以指向一個無參數無傳回值的方法。
ParameterizedThreadStart委託可以指向一個有參數無傳回值的方法。

Thread類執行個體化的時候可以向建構函式傳入ThreadStart委託的執行個體或ParameterizedThreadStart委託的執行個體,然後使用Thread.Start()以非同步方式調用一個方法。

2) 為需要非同步執行的耗時方法定義一個委託,使用該委託的執行個體的BeginInvoke方法來非同步呼叫該方法,BeginInvoke方法附帶了AsyncCallback類型的回呼函數委託以及object類型的參數。
然後可以在AsyncCallback類型的回呼函數中使用EndInvoke方法來得到非同步方法呼叫的傳回值。

3) 使用ThreadPool.QueueUserWorkItem(new WaitCallback(method))來向線程池添加一個新線程

4) 可以使用System.Timers.Timer定時器類來實現在新線程中執行耗時操作,System.Timers.Timer定時器不同於System.Windows.Forms.Timer定時器,System.Timers.Timer定時器的定時事件的響應函數並不是在調用定時器Start方法的線程中去執行。

5) 可以使用BackgroundWorker組件來實現在新線程中執行耗時操作(通過訂閱DoWork事件).

問題2的解決方案
以下代碼是.NetFramework 2.0類庫中避免多線程修改介面造成的臨界資源死結問題的代碼。
System.Windows.Forms.Control.get_Handle方法的內部實現

public IntPtr get_Handle()
{
    if ((checkForIllegalCrossThreadCalls && !inCrossThreadSafeCall) && this.InvokeRequired)
    {
        throw new InvalidOperationException(SR.GetString("IllegalCrossThreadCall", new object[] { this.Name }));
    }
    if (!this.IsHandleCreated)
    {
        this.CreateHandle();
    }
    return this.HandleInternal;
}

在修改每個控制項的屬性的時候,都會先調用get_Handle方法擷取一個操作控制代碼,在該方法內部會判斷Control類的靜態成員CheckForIllegalCrossThreadCalls的值(該成員用來表示是否啟用安全模式,安全模式的意思就是禁止跨線程修改介面屬性來避免多線程訪問臨界資源死結的問題),第二個判斷的屬性是InvokeRequired屬性(該屬性用來表示當前方法是否是在跨線程調用)。 所以我們可以通過修改CheckForIllegalCrossThreadCalls屬性為False來關閉安全模式,但有可能造成線程死結問題。

解決方案只有兩個
1) 設定CheckForIllegalCrossThreadCalls屬性為False,關閉.net的安全模式,在對介面屬性修改的代碼加上lock,來實現同一時間僅有一個線程修改介面屬性。
2) 在設定介面屬性的方法中詢問InvokeRequired屬性,如果是非介面線程修改介面屬性,則讓介面線程來調用設定介面屬性的方法。(這個方法是MSDN執行個體中慣用的方法,也是BackgroundWorker等組件的內部實現方式)

推薦大家使用BackgroundWorker來實現耗時操作的輔助線程以及跨線程修改介面屬性等操作,關於BackgroundWorker的具體使用方法見 一日一練 之 BackgroundWorker
http://www.cnblogs.com/coderlee/archive/2007/12/27/1017620.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.