C# 如何在多线程环境下从TargetInvocationException中优雅地恢复?
在另一个线程中执行长进程时,由于UI线程(进度条)上的windows控件,我遇到了TargetInvocationException。此异常导致我的应用程序崩溃(转到调试中的main方法),并且无法被try-catch捕获。C# 如何在多线程环境下从TargetInvocationException中优雅地恢复?,c#,multithreading,exception,C#,Multithreading,Exception,在另一个线程中执行长进程时,由于UI线程(进度条)上的windows控件,我遇到了TargetInvocationException。此异常导致我的应用程序崩溃(转到调试中的main方法),并且无法被try-catch捕获。 我找出了这个异常的原因,并修复了它(即试图通过一个超过最大值的值来分配“Value”属性)。但这让我想知道如何捕捉这样的异常(在生产代码中),因此我可以选择恢复我的应用程序,而不是终止应用程序。很可能您无法恢复太多。就您的操作而言,大量堆栈帧(以及从这些堆栈帧引用的对象)的
我找出了这个异常的原因,并修复了它(即试图通过一个超过最大值的值来分配“Value”属性)。但这让我想知道如何捕捉这样的异常(在生产代码中),因此我可以选择恢复我的应用程序,而不是终止应用程序。很可能您无法恢复太多。就您的操作而言,大量堆栈帧(以及从这些堆栈帧引用的对象)的状态可能由于错误而无效 因此,您最多可以在非常高的级别上进行恢复,然后重试该操作 如果您正在访问的资源能够包含在事务中,那么我建议您这样做,这样您就不必担心持久化数据中的不一致性 此外,您可能希望在上签出此线程,以便: 以及来自Microsoft的异常处理应用程序块:
捕获异常并找到一种机制将其传递回主代码或调用代码。您可以通过静态事件
应用程序在GUI线程上“处理”异常(实际上,您只是接收到它们的通知)。未处理的异常
将处理程序附加到此事件时,将对WinForms UI(消息泵)线程上所有未处理的异常调用该处理程序。附加此处理程序意味着
应用程序将不会退出。如果没有它,WinForms将关闭您的应用程序。如果3.0+版本的.net可以按照这些思路进行操作,则不确定您使用的是哪个版本的.net
private void UpdateValue(int newValue)
{
Action myAction = () => progressBar.Value = newValue;
if (progressBar.InvokeRequired)
progressBar.Invoke(myAction);
else
myAction();
}
使用进度条的新值调用此方法,它将检查调用是否需要编组并进行适当的调用。小心InvokeRequired相对昂贵,所以只在需要的地方使用它。如果需要,您可以将其转换为一个扩展方法,以便将此模式用于其他控件
希望这能有所帮助。@Dean:异常不是由从另一个线程访问UI线程引起的,这种情况是正确实现的。比如说,在您的示例中调用(myAction)时,异常会被抛出,无法被捕获。试试看。。。感谢you@casperOne:“就您的操作而言,由于错误,大量堆栈帧(以及从这些堆栈帧引用的对象)的状态可能无效。”这似乎是最可能的因素,在我的例子中,异常已被重复抛出600多次。