如何在多线程中优雅地从TargetInvocationException恢复?

时间:2009-03-09 19:53:32

标签: c# multithreading exception

我在另一个线程中执行长进程时遇到了TargetInvocationException,这是由UI线程上的Windows控件引起的(进度条)。此异常导致我的应用程序崩溃(在调试中转到main方法)并且无法通过try catch捕获。 我弄清楚了什么造成了这个异常,并修复了它(试图通过超过最大值的值来分配“Value”属性)。但它让我想知道如何捕获这样的异常(在生产代码中),所以我可以选择恢复我的应用程序,而不是终止应用程序。

4 个答案:

答案 0 :(得分:2)

你很可能无法恢复得很多。就您的操作而言,由于错误,大量堆栈帧(以及从这些堆栈帧引用的对象)的状态可能无效。

因此,您最多可以恢复到非常高的水平并再次尝试操作。

如果您正在访问的资源能够包含在事务中,那么我建议您这样做,这样您就不必担心持久化数据中的不一致。

另外,您可能想在SO上查看此主题:

Best Practice for Exception Handling in a Windows Forms Application?

以及Microsoft的异常处理应用程序块:

http://msdn.microsoft.com/en-us/library/cc309505.aspx

答案 1 :(得分:2)

您可以通过静态事件Application.UnhandledException在GUI线程上“处理”异常(实际上,您只是接收它们的通知)。

当您将处理程序附加到此事件时,将为WinForms UI(消息泵)线程上的所有未处理异常调用它。您附加此处理程序的事实意味着Application不会退出。没有它,WinForms会关闭你的应用程序。

答案 2 :(得分:0)

捕获异常并找到一种机制将其传递回main或调用代码。

答案 3 :(得分:0)

不知道你使用的.net版本是什么版本,如果你的3.0+可以按照这些方式做点什么。

private void UpdateValue(int newValue)
{
    Action myAction = () => progressBar.Value = newValue;

    if (progressBar.InvokeRequired)
        progressBar.Invoke(myAction);
    else
        myAction();
}

使用进度条的新值调用此方法,它将检查调用是否需要编组并进行适当的调用。注意InvokeRequired相对昂贵,所以只在需要的地方使用它。您可以将其转换为扩展方法,以便在需要时将此模式一般性地用于其他控件。

希望这有帮助。