在不同线程中创建WPF窗口时出现异常

4
我有一个WPF应用程序,我在不同的线程中运行一些动画,这样我的主UI线程就会响应。我正在使用这里发布的代码:
Thread thread = new Thread(() =>
{
    Window1 w = new Window1();
    w.Show();

    w.Closed += (sender2, e2) => w.Dispatcher.InvokeShutdown();

    System.Windows.Threading.Dispatcher.Run();
});

thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

通常情况下它都能正常工作,但是在系统部署后,我收到了一个应用崩溃的投诉,并附上以下堆栈跟踪信息:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.Generic.List`1.RemoveAt(Int32 index)
   at System.IO.Packaging.PackagePart.CleanUpRequestedStreamsList()
   at System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
   at System.IO.Packaging.PackagePart.GetStream()
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)   
   at Window1.xaml:line 1   
   at Window1..ctor()

有人看到过这个异常吗?能解释一下发生了什么吗?这个特定异常的原因是什么?
我正在使用 .Net 3.5 SP1

1个回答

2

看起来 System.Windows.Application.LoadComponent 不是线程安全的,所以你对 Window 构造函数的调用可能会导致错误。

你可以尝试在主线程中创建窗口实例,然后在新线程中显示它,但我不确定这是否适合你的应用程序需求。


听起来像是一个解决方案 :-) 你有任何额外的参考资料来支持这个假设吗?由于它只在现场发生了一次,我无法进行测试... - Amittai Shapira
不,这只是一个想法。您可以查看System.Windows.Application.LoadComponent的代码,以查找其中的线程安全问题。或者您可以尝试使用在不同线程上同时创建许多窗口的测试来压力测试LoadComponent,以重现此错误。 - Nikolay
好的,谢谢。我会看一下 - 我已经给你点赞了,并且在确认这是异常的真正根本原因后,我会接受这个答案。 - Amittai Shapira
看起来这就是问题所在——在单独的线程中创建许多这样的用户控件有时会失败。我已经在用户控件的创建上添加了锁定——谢谢! - Amittai Shapira
我很惊讶这是一个被接受的解决方案:难道Windows(就像所有其他DependencyObjects一样)不是绑定在它们被创建的线程上吗?也就是说,从另一个线程访问它们会导致AccessViolationException异常?因此,在一个线程上创建它们,然后在另一个线程上显示它们是不可能的... - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接