2014-07-17 95 views
3

我對編程和WPF體系結構很新穎。我有一個使用backgroundworker類的WPF應用程序。然而,它總是會拋出錯誤「調用線程必須穩定,因爲許多UI組件都需要這個」。我需要添加我主要方法的STAThread屬性。但我不知道如何做到這一點。如何讓背景工作在WPF應用程序中工作

public partial class MainWindow : Window 
    { 
public MainWindow() 
     { 
      InitializeComponent(); 

      this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();   

      InitializeBackgroundWorker(); 
      Thread.CurrentThread.SetApartmentState(ApartmentState.STA); 
      tabItemList.CollectionChanged += this.TabCollectionChanged; 
     } 
} 


private void InitializeBackgroundWorker() 
     { 
      backgroundWorker1.DoWork += 
       new DoWorkEventHandler(backgroundWorker1_DoWork); 
      backgroundWorker1.RunWorkerCompleted += 
       new RunWorkerCompletedEventHandler(
      backgroundWorker1_RunWorkerCompleted); 
      backgroundWorker1.ProgressChanged += 
       new ProgressChangedEventHandler(
      backgroundWorker1_ProgressChanged); 
     } 

     // This event handler is where the actual, 
     // potentially time-consuming work is done. 
     private void backgroundWorker1_DoWork(object sender, 
      DoWorkEventArgs e) 
     { 
      // Get the BackgroundWorker that raised this event. 
      BackgroundWorker worker = sender as BackgroundWorker; 

      // Assign the result of the computation 
      // to the Result property of the DoWorkEventArgs 
      // object. This is will be available to the 
      // RunWorkerCompleted eventhandler. 
      //e.Result = AddTabitem((int)e.Argument, worker, e); 
      AddTabitem((string)e.Argument, worker, e); 
     } 

void AddTabitem(string filePath, BackgroundWorker worker, DoWorkEventArgs e) 
     { 
      if (File.Exists(filePath)) 
      { 
//This line which throws error "the calling thread must be sta because many ui components require this" 
       RichTextBox mcRTB = new RichTextBox(); 
       rtbList.Add(mcRTB); 
} 
+1

分開。 – Dbl

+0

幾乎沒有理由爲什麼你應該考慮使用'BackgroundWorker'。首先,如果你使用MVVM/Binding,你會有自動的UI線程編組。另一方面,對於任何I/O綁定操作,您應該使用Task.Run來執行任何CPU綁定計算和異步任務I/O。 – Aron

回答

2

你必須設置線程啓動前的ApartmentState

http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx

要設置單元狀態上的WPF應用程序,
[STAThread]屬性添加到您的應用程序,如this

public partial class App : Application 
{ 
    App() 
    { 
     InitializeComponent(); 
    } 

    [STAThread] 
    static void Main() 
    { 
     Window1 window = new Window1(); 
     App app = new App(); 
     app.Run(window); 
    } 
} 
+0

當我添加這部分代碼時,它會拋出一個錯誤,說'Editor.App'已經使用相同的參數類型定義了一個名爲'Main'的成員。我確實發現在App.g.cs中存在一個Main(),我也看到在System()之前添加了[System.STAThreadAttribute()]。那麼爲什麼我的程序仍然會拋出錯誤? – savi

+0

抱歉,我錯過了必須將應用程序的構建操作從「應用程序定義」更改爲「頁面」的步驟。即使在我運行應用程序後仍然會拋出「調用線程必須穩定,因爲許多UI組件都需要這個」。我在questio中添加了AddTabItem代碼,以顯示錯誤的確切位置。我在這裏做錯了什麼? – savi

+2

使用this.Dispatcher.Invoke((Action)(()=> { ... //您的代碼在這裏。 }));解決了我的問題 – savi

1

編輯:

核爆我一點關於STAThread ,因爲這不是你的問題。

在審閱更新後臺工作者代碼後,您正試圖從後臺工作線程更新UI。正如你所經歷的那樣,這是行不通的。你有幾個選項:

1)而不是直接更新該RichTextBox,而是更新一個變量,你有數據綁定到你正在更新的屬性。請參閱本文以獲取有關數據綁定的概述,因爲您聲明您是WPF的新手: http://msdn.microsoft.com/en-us/library/ms752347(v=vs.110).aspx

2)使用Invoke而不是直接設置屬性。無論如何,您可能需要爲選項1執行此操作。這可能是您最直接的快速解決方案。這裏是一個很好的理由的WPF調度這是你需要做這個調用業務內容:http://tech.pro/tutorial/800/working-with-the-wpf-dispatcher

它的工作是這樣的: mcRTB.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Normal, 新行動( 代表() { mcRTB.Text =「hello」; } ));

以上是更改屬性。你可以調整它來調用你的rtbList的.Add方法。

3)想避免調用?使用你的背景工作人員的報告進度!當你在BW中告訴它時,這個事件觸發,然後你可以在主UI線程上做一些工作,而不必擔心調用東西。

當你初始化你的體重,在那裏釘這樣的:

backgroundWorker1.WorkerReportsProgress = true; 
backgroundWorker1.ProgressChanged += new ProgressChanged EventHandler(backgroundWorker1_ProgressChanged); 
在您的通話

然後回到你做(或已自動創建爲你使用+ =)在您的UI線程,你可以做的工作。你可以告訴你的體重做這個報告一些進展:

// the int in the first parameter is arbitrary 
// the object can be any object. This is how you pass actual data to your call back 
backgroundWorker1.ReportProgress(1,new object()) 

下面是報告進展情況很好看的: http://msdn.microsoft.com/en-us/library/a3zbdb1t(v=vs.110).aspx

從demoncodemonkey的答案,你應該看看「任務」級同意
+0

它給出了一個錯誤,Arrtribute'STAThread'在這個聲明類型上是無效的。它只對'方法'聲明有效。 – savi

+0

你說得對,它應該是主要的入口點方法。請參閱demoncodemonkey的正確位置的答案。不過,你不應該需要一個STAThread來讓後臺工作者完成它的工作。你能發佈所有與後臺工作人員相關的代碼嗎? –

+0

添加了詳細顯示後臺工作人員的剩餘代碼。 – savi

相關問題