2013-01-07 23 views
0

我有這個在我的App.xaml:WPF CrossThreadException在App.xaml中與BackgroundWorker的

public App() 
{ 
    _backgroundWorker = new BackgroundWorker(); 
    _backgroundWorker.DoWork += new DoWorkEventHandler(DoBackgroundWork); 
    _backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundCompleted); 
    _backgroundWorker.RunWorkerAsync(); 

    _splashView = new SplashView(); 
    _splashView.Show(); 
} 

DoBackgroundWork方法執行某些數據庫設置,然後BackgroundCompleted事件關閉_splashView並顯示_mainView

但是,從BackgroundCompleted修改_splashView中的任何內容都會導致出現交叉線程異常,這是我通過後臺工作人員設計要解決的問題。我猜這跟App.Xaml背景工作的方式有關。也許這是一個糟糕的方式來做閃屏?

回答

-1

無法保證哪個線程將使用OnWorkCompleted的事件處理程序來執行。

查看類似的問題BackgroundWorker OnWorkCompleted throws cross-thread exception

您必須使用InvokeBeginInvoke方法來修改從後臺線程的視覺元素。您可以直接在要修改其屬性的對象上調用它或使用Dispatcher

編輯:由於每個對話與亞當

SynchronizationContext先後爲OnWorkCompleted事件處理程序進行初始線程上運行所需的效果(而不是BackgroundWorker的的)。 http://msdn.microsoft.com/en-us/magazine/gg598924.aspx。 (請參見圖2)

如果BackgroundWorker在SynchronizationContext初始化之前創建並運行,那麼OnWorkCompleted將在可能與BackgroundWorker相同的線程上執行。

謝謝亞當。

+1

對,我已經添加了BeginInvoke使它工作。我想知道爲什麼我在BackgroundCompleted中需要這個。這個事件不應該在UI線程上觸發嗎?我認爲這是BackgroundWorkers的重點。 – ConditionRacer

+0

@ Justin984對不起,我錯過了'BackgroundCompleted'拋出異常。它正在拋出,因爲不能保證該方法將在哪個線程上執行。邏輯會決定它應該返回到具有事件處理程序的線程,但事實並非如此。 [相似解答](http://stackoverflow.com/questions/818767/backgroundworker-onworkcompleted-throws-cross-thread-exception) –

+0

有趣!我不知道。所以即使在UI線程上創建了backgroundworker,它的完成事件也不能保證在UI線程上觸發?我有一些代碼來解決! – ConditionRacer

0

後臺工作者使用SynchronizationContext。這是從內存,但我不認爲它已被初始化在應用程序的構造函數。

在構造BW檢查之前,SynchronizationContext.Current不爲空。 同時檢查SynchronizationContext.Current在構建BW之前和完成的方法中是否相同。

如果不是的話,你需要在後面的過程移動代碼... App.OnStartUp應該罰款

0

也許這是一個壞的方式做一個閃屏?

除非我錯誤地解釋了你的問題,我不認爲有必要這樣做來顯示啓動畫面。只需選擇圖像,然後在「屬性」窗口中單擊BuildAction下拉列表並選擇SplashScreen。另外,我認爲您可以通過消除BackgroundWorker來簡化您的流程,除非您的數據功能需要很長時間。我相信你已經添加了它來適應啓動畫面的顯示/隱藏。

+0

我們的啓動畫面有一個進度欄,所以很遺憾,我無法將其替換爲圖片。後臺工作是因爲有一些數據庫設置的東西需要大約10秒才能完成。 – ConditionRacer