偶尔会发生System.InvalidOperationException和System.Reflection.TargetInvocationException

时间:2010-02-19 19:08:13

标签: c# wpf multithreading

运行我的程序时,有时我会得到这些例外,有时候我没有。这是执行流程:

用户单击Window1类中的按钮 类收集输入,启动backgroundWorker.RunWorkerAsync() 在DoWork中,调用App.doStuff() 在App.doStuff()中,我创建了另一个线程来在不同的窗口中显示进度条,如下所示:

Thread newWindowThread =  new Thread(new ThreadStart(showProgressMethod));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();

在showProgressMethod()中,我这样做:

progressWindow = new MyProgressWindow(this);
progressWindow.Show();
System.Windows.Threading.Dispatcher.Run();

现在,如果我第一次运行它,我从来没有遇到任何问题。但是当/如果我完成后重做操作,那么我可能会得到例外。

查看代码,我通过调用dispatcher.Run()和Thread.Start()来感觉我做错了什么,但是我不太了解线程模型,所以我不是肯定的。

无论哪种方式,在第一次运行时,程序永远不会做任何异常。但有时当我再次单击该按钮以激活该过程时,则会发生异常。我认为当程序没有足够的时间清理时会发生这种情况?我不确定。

修改

似乎问题是ProgressWindow线程没有结束。显然在ProgressWindow中的App.doStuff()或Dispatcher.Thread.Abort()中添加一个Thread.Abort()可以解决问题。显然。

但是,由于Abort()方法,它仍然会引发异常,尽管它不再崩溃。我也不明白为什么关闭ProgressWindow不会结束线程。从我使用Thread.Abort()读到的内容并不是一个好习惯,但我不明白为什么。

编辑2

Thread.Abort有时还会崩溃。所以,我所做的是:
按建议替换Show() ShowDialog() System.Windows.Threading.Dispatcher.Run();来电 删除对{{1}}

的调用

3 个答案:

答案 0 :(得分:0)

MyProgressWindow内有什么?也许它可以访问一些ResourceDictionary两次,一次从第一个newWindowThread开始,一次从第二个开始? ResourceDictionary s不能在两个线程之间共享。

答案 1 :(得分:0)

a)TargetInvocationException将是InnerException属性中的真正异常 - 检查它。

b)你确定你没有重复/接触来自两个不同线程的对象吗?如果WPF检测到从创建它的dependencyproperty之外的线程访问的依赖项属性,则显式抛出。

答案 2 :(得分:0)

  

用户单击Window1类中的按钮。   类收集输入,启动backgroundWorker.RunWorkerAsync()。   在DoWork中,调用App.doStuff()。   在App.doStuff()中,我创建另一个线程来显示进度条......

现在你有了在UI线程上运行的代码,在BackgroundWorker线程上运行的代码,以及在新的第三个线程上运行的代码,这个代码不是UI线程,而且正在更新UI元素。我有这个权利吗?因为这听起来几乎肯定是一个问题。

修改

我很惊讶你正在做的事情,而不是它的工作不一致。

ProgressChanged的{​​{1}}事件是您希望用于在后台运行的方法与用户界面之间的互操作。它在UI线程上运行。