【问题标题】:How to recover gracefully from TargetInvocationException in multi thread?如何在多线程中从 TargetInvocationException 中优雅地恢复?
【发布时间】:2009-03-09 19:53:31
【问题描述】:

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

【问题讨论】:

    标签: c# multithreading exception


    【解决方案1】:

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

    正因为如此,充其量你可以恢复到很高的水平,然后再次尝试操作。

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

    另外,您可能想在 SO 上查看此线程:

    Best Practice for Exception Handling in a Windows Forms Application?

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

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

    【讨论】:

    • @casperOne:“就您的操作而言,大量堆栈帧(以及从这些堆栈帧引用的对象)的状态可能由于错误而无效。”这似乎是最可能的因素,在我的情况下,异常已被重复抛出 600 多次。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        不确定您使用的是哪个版本的 .net,如果它是 3.0+,您可以按照这些思路做一些事情。

        private void UpdateValue(int newValue)
        {
            Action myAction = () => progressBar.Value = newValue;
        
            if (progressBar.InvokeRequired)
                progressBar.Invoke(myAction);
            else
                myAction();
        }
        

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

        希望这会有所帮助。

        【讨论】:

        • @Dean:不是从其他线程访问UI线程引起的异常,这种情况是正确实现的。它什么时候,让我们说在你的例子中调用(myAction),那里抛出异常并且不能被捕获。试试看...谢谢
        猜你喜欢
        • 2012-10-02
        • 2011-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-14
        • 1970-01-01
        相关资源
        最近更新 更多