2010-02-19 79 views
1

当运行我的程序时,有时我会得到这些异常,其他时候我不会。这是执行流程:System.InvalidOperationException和System.Reflection.TargetInvocationException偶尔发生

用户单击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()不是很好的做法,虽然我不明白为什么。

EDIT 2

Thread.Abort的仍然保留着它有时崩溃。所以,我所做的就是:
更换Show()呼吁ShowDialog(),作为建议和
取出呼吁System.Windows.Threading.Dispatcher.Run();

回答

0

里面是什么MyProgressWindow?也许它会从第一个newWindowThread一次访问一次ResourceDictionary两次,一次从第二次? ResourceDictionary s不能在两个线程之间共享。

+0

ProgressWindow仅具有对mainWindow.backgroundWorker的引用。 ProgressWindow中的关闭事件调用backgroundWorker.CancelAsync() - 如果关闭ProgressWindow,则取消该任务。我评论说,这些线路阻止它做任何事情,并没有这样做。 – zxcvbnm 2010-02-19 19:24:31

0

a)TargetInvocationException将在InnerException属性中出现真正的异常 - 请检查该异常。

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

+0

好吧,当进度窗口关闭时,我启用主窗口,当backgroundworker线程结束时,关闭进度窗口。所以我正在访问其他线程资源,但我打电话给调度员,并使用BeginInvoke,所以我认为我是这样做的正确方法。 – zxcvbnm 2010-02-20 15:27:57

+0

是的,这是正确的方式。但要确保你有合适的调度员。 – 2010-02-21 03:57:35

0

用户单击Window1类中的按钮。 类收集输入,backgroundWorker.RunWorkerAsync()已启动。 在DoWork中,调用App.doStuff()。 内App.doStuff(),我好,你现在的代码在UI线程上运行时创建另一个线程来显示进度...

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

编辑:

我很惊讶,你在做什么工作可言,而不是它的工作原理不一致。

BackgroundWorkerProgressChanged事件是您希望用于在后台运行的方法和用户界面之间进行互操作的方式。它在UI线程上运行。

+0

是的,这就是我正在做的事情。第三个线程中的代码控制是否启用该窗口 - 如果进度条处于活动状态,则禁用该窗口以防止用户多次启动该进程。那么我该如何去做呢? – zxcvbnm 2010-02-20 15:25:50

+0

我已经使用progresschanged更新进度窗口中的进度条。但我仍然需要创建第三个线程才能显示进度窗口。我认为。也许有一种方法可以在ui使用的同一个线程中创建进度窗口,然后用backgroundworker做数学运算,但我不知道。 – zxcvbnm 2010-02-20 19:59:33

+0

您可以只使用Window.Show(),它将通过调度程序进行泵送。这不是一个阻塞的电话。然而,ShowDialog()是。 – 2010-02-21 03:58:48

相关问题