带有BackgroundWorker的App.Xaml中的WPF CrossThreadException

时间:2013-01-07 19:11:27

标签: c# wpf backgroundworker

我在App.Xaml中有这个:

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

但是,从_splashView修改BackgroundCompleted中的任何内容都会导致跨线程异常,这就是我设计的后台工作者修复的问题。我猜这与backgroundworker在App.Xaml中的工作方式有关。也许这是制作启动画面的坏方法?

3 个答案:

答案 0 :(得分:0)

后台工作程序使用SynchronizationContext。这是从内存开始的,但我不认为它已在App构造函数中初始化。

在构造BW之前,检查SynchronizationContext.Current不为null。 同时检查SynchronizationContext.Current在构造BW之前和已完成的方法中是相同的。

如果不是,您需要稍后在此过程中移动代码... App.OnStartUp应该没问题

答案 1 :(得分:0)

  

这可能是制作启动画面的不好方法吗?

除非我误解了你的问题,否则我认为没有必要这样做以显示闪屏。只需选择图像,然后在“属性”窗口中单击BuildAction下拉列表,然后选择SplashScreen。此外,我认为您可以通过消除BackgroundWorker来简化您的流程,除非您的数据功能需要很长时间。我相信你添加了它来容纳启动画面的显示/隐藏。

答案 2 :(得分:-1)

无法保证OnWorkCompleted的事件处理程序将用于执行哪个线程。

查看类似问题BackgroundWorker OnWorkCompleted throws cross-thread exception

您必须使用InvokeBeginInvoke方法修改后台线程中的可视元素。您可以直接在要修改其属性的对象上调用它,或使用Dispatcher

编辑:根据与Adam的谈话

SynchronizationContext具有在初始线程(而不是BackgroundWorker)上运行OnWorkCompleted事件处理程序所需的效果。 http://msdn.microsoft.com/en-us/magazine/gg598924.aspx。 (见图2)

如果在SynchronizationContext初始化之前创建并运行BackgroundWorker,则OnWorkCompleted将在与BackgroundWorker相同的线程上执行。

感谢Adam。