1. 程式人生 > >執行緒間操作無效: 從不是建立控制元件的執行緒訪問它的三種解決方法

執行緒間操作無效: 從不是建立控制元件的執行緒訪問它的三種解決方法

今天遇到這個問題,百度了下,把解決的方法總結出來。
我們在ui執行緒建立的子執行緒操作ui控制元件時,系統提示錯誤詳細資訊為:
執行緒間操作無效: 從不是建立控制元件“XXX”的執行緒訪問它。

就我知道的有三種方法,先看一下msdn的介紹:

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

看下解決辦法吧

1、把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.";
}

博主轉後註釋:需要非同步時,把獲取資料的程式碼寫在BackgroundWork控制元件的DoWork事件中並把獲取到的資料賦值給e.Result,然後在RunWorkerCompleted事件中接收e.Result並賦值給控制元件。

大家可以參考下MSDN:
如何:對 Windows 窗體控制元件進行執行緒安全呼叫

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


轉載自:http://www.cnblogs.com/luckboy/archive/2010/12/19/1910785.html