線程間操作無效:從不是創建控件的線程訪問它的三種方法


訪問 Windows 窗體控件本質上不是線程安全的。如果有兩個或多個線程操作某一控件的狀態,則可能會迫使該控件進入一種不一致的狀態。還可能出現其他與線程相關的 bug,包括爭用情況和死鎖。確保以線程安全方式訪問控件非常重要。

 

解決辦法

1、把CheckForIllegalCrossThreadCalls設置為false

在多線程程序中,新創建的線程不能訪問UI線程創建的窗口控件,如果需要訪問窗口中的控件,可以在窗口構造函數中將CheckForIllegalCrossThreadCalls設置為 false

public Form1()
{
    InitializeComponent();
    CheckForIllegalCrossThreadCalls = false;
}

也可以針對某一控件進行設置,例如:

TextBox.CheckForIllegalCrossThreadCalls = false;

 

2、利用委托

        delegate void SetTextCallBack(string text);
        private void SetText(string text)
        {
            if (this.txt_a.InvokeRequired)
            {
                SetTextCallBack stcb = new SetTextCallBack(SetText);
                this.Invoke(stcb , new object[] { text});
            }
            else
            {
                this.txt_a.Text = text;
            }
        }
 
        private void LoadData()
        {
            SetText("測試");
        }
 
 
        //窗體加載時,用線程加載數據
        private void Frm_ImportManager_Load(object sender, EventArgs e)
        {
            ThreadStart ts = new ThreadStart(LoadData);
            Thread thread = new Thread(ts);
            thread.Name = "LoadData";
            thread.Start();
        }    

 

3、使用 BackgroundWorker控件

在應用程序中實現多線程的首選方式是使用 BackgroundWorker 組件。BackgroundWorker 組件使用事件驅動模型實現多線程。輔助線程運行 DoWork 事件處理程序,創建控件的線程運行ProgressChanged 和 RunWorkerCompleted 事件處理程序。注意不要從 DoWork 事件處理程序調用您的任何控件。

下面的代碼示例不異步執行任何工作,因此沒有 DoWork 事件處理程序的實現。TextBox 控件的Text 屬性在 RunWorkerCompleted 事件處理程序中直接設置。

        // This event handler starts the form's 
        // BackgroundWorker by calling RunWorkerAsync.
        //
        // The Text property of the TextBox control is set
        // when the BackgroundWorker raises the RunWorkerCompleted
        // event.
        private void setTextBackgroundWorkerBtn_Click(
            object sender, 
            EventArgs e)
        {
            this.backgroundWorker1.RunWorkerAsync();
        }
        
        // This event handler sets the Text property of the TextBox
        // control. It is called on the thread that created the 
        // TextBox control, so the call is thread-safe.
        //
        // BackgroundWorker is the preferred way to perform asynchronous
        // operations.

        private void backgroundWorker1_RunWorkerCompleted(
            object sender, 
            RunWorkerCompletedEventArgs e)
        {
            this.textBox1.Text = 
                "This text was set safely by BackgroundWorker.";
        }  

 

大家可以參考下MSDN:如何對 Windows 窗體控件進行線程安全調用

http://msdn.microsoft.com/zh-cn/visualc/ms171728(VS.85,printer).aspx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM