2013-01-07 63 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