2012-02-18 130 views
0

我有一會兒了問題跨線程異常

這一行:

txtPastes.Text = (string)e.UserState; 

拋出一個跨線程異常,我沒有找到任何解決辦法

txtPastes - 文本

GuiUpdate - BackgroundWorker

lstAllPastes - 字符串列表

private void GuiUpdate_DoWork(object sender, DoWorkEventArgs e) 
    { 
     while (true) 
     { 
      while (lstAllPastes.Count == 0) ; 

      for (int i = 0; i < lstAllPastes[0].Length; i++) 
      { 
       GuiUpdate.ReportProgress(0, lstAllPastes[0].Substring(0, i)); 
       Thread.Sleep(1); 
      } 
      lstAllPastes.RemoveAt(0); 
     } 
    } 

    private void GuiUpdate_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     txtPastes.Text = (string)e.UserState; 
    } 

    private void GuiUpdate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 

    } 
+2

這是WinForms還是WPF? – Douglas 2012-02-18 16:16:09

+3

您沒有找到任何解決方案?這可能是在GUI應用程序中使用線程時最常見的問題。 – svick 2012-02-18 16:23:40

+0

WinForm ........ – maryum375 2012-02-18 17:02:29

回答

5

您無法更新從比其他任何線程UI控件UI線程。通常,BackgroundWorker將負責在UI線程上正確提升其ProgressChangedRunWorkerCompleted事件。由於不會出現在這裏是這樣,你可以封你的用戶界面,更新邏輯的UI使用Invoke方法線程自己:

txtPastes.Invoke(new Action(() => 
{ 
    // This code is executed on the UI thread. 
    txtPastes.Text = (string)e.UserState; 
})); 

如果你在WPF中,你需要調用Invoke在控制的調度員:

txtPastes.Dispatcher.Invoke(new Action(() => 
{ 
    txtPastes.Text = (string)e.UserState; 
})); 

更新:正如托馬斯·萊韋斯克和漢斯帕桑特所提到的,您應該調查爲什麼你的ProgressChanged事件沒有被UI線程上提出的原因。我的懷疑是,如果在初始化txtPastes文本框之前引發了第一個ProgressChanged事件,那麼您在應用程序初始化生命週期中過早啓動BackgroundWorker,這可能會導致競爭狀況,並可能導致NullReferenceException

+0

我在initializecomponent()後啓動BGW() – maryum375 2012-02-18 16:58:22

0

如果要更新例如文本框YOUT GUI,你應該看看這篇文章:

Update GUI from another thread

+0

ProgressChanged應該在UI線程上運行,所以在這裏不需要使用Invoke – 2012-02-18 16:40:00

1

確保您從UI線程啓動BackgroundWorker;如果這樣做,將在該線程上引發ProgressChanged事件,並且不會發生異常。

+0

我正在啓動backgroundWorker來自gui線程 – maryum375 2012-02-18 16:46:11

1

嗯,這應該是當然的工作。此異常的原因在代碼段中不可見。重要的是BackgroundWorker的啓動時間和位置。它的RunWorkerAsync()方法使用SynchronizationContext.Current屬性來確定需要執行ProgressChanged事件處理程序的線程。

  • 你開始BGW太早,Application.Run()調用之前:

    時,這可能會出錯。 Winforms或WPF還沒有機會安裝自己的同步提供程序。

  • 您在工作線程中調用了BGW的RunWorkerAsync()方法。只支持封送到UI線程,消息循環是在另一個線程上運行代碼的關鍵要素。
  • 具有txtPastes控件的窗體是在另一個線程上創建的。隨着BGW在UI線程上啓動,仍然是線程不匹配
  • 窗體的Show()方法在另一個線程上調用。它在錯誤的線程上創建本機Windows窗口。
+0

「它的構造函數使用SynchronizationContext.Current」:不正確;檢查反射器;)。當你使用RunWorkerAsync啓動BGW時,通過使用AsyncOperation類 – 2012-02-18 16:39:05

+0

謝謝,更正了同步上下文。 – 2012-02-18 16:45:47

+0

是的,這是真的我真的開始在Windows構造函數的背景工作的工作,現在我通過將它移動到私人無效Main_Load固定它,當窗體加載 ,但仍然是相同的問題 – maryum375 2012-02-18 16:56:17