【问题标题】:Unhandled exception occurs after handling exception处理异常后出现未处理异常
【发布时间】:2018-12-10 16:00:09
【问题描述】:

这个主题来自我之前的问题:How to remove and create log in Windows Event Viewer

我创建了 wpf 应用程序。我通过 3 种方式捕获未处理的异常:

public partial class App : Application
{
    public App()
    {
        DispatcherUnhandledException += App_DispatcherUnhandledException;
        Dispatcher.UnhandledException += Dispatcher_UnhandledException;
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {

    }

    private void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {

    }

    private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {

    }
}

我正在创建这样的异常:

   public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        throw new Exception("Test exception");
    }
}

在执行方法(Dispatcher_UnhandledExceptionCurrentDomain_UnhandledExceptionApp_DispatcherUnhandledException)之后,仍然抛出这个异常。并且 Windows 事件查看器正在创建这样的日志

描述:进程因未处理的异常而终止。 异常信息:System.InvalidOperationException 在 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(System.Data.Common.DbConnection,System.Threading.Tasks.TaskCompletionSource1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal, System.Data.ProviderBase.DbConnectionInternal ByRef) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory, System.Threading.Tasks.TaskCompletionSource1

【问题讨论】:

  • 你的意思是当抛出异常时,这三个方法实际上都没有被调用?当您说“执行方法后 (...)”时,我不太确定您的意思。
  • 您可能应该修复原始异常,或者至少记录它,而不是试图隐藏它。失败的数据库连接不会自行修复。
  • 将事件参数的handled设置为true以停止事件传播。

标签: c# wpf unhandled-exception


【解决方案1】:

在您的处理程序方法中,您需要告诉 .NET 您处理了异常。否则它仍然会杀死应用程序。您可以使用DispatcherUnhandledExceptionEventArgs 对象的Handled 属性来完成此操作。

因此,如果您决定不顾异常继续应用程序,请将其设置为true

private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
    e.Handled = true; //let's continue and see if anything explodes
}

也就是说,您仍然应该处理可能发生的异常(尽可能多地)。以您给出的示例为例,这看起来像是网络连接问题。如果您在创建连接时发现该异常,您可以告诉用户更具体的信息,例如“我无法连接到数据库。您的网络正常吗?”而如果您依靠它来捕获此类错误,则只能反刍异常消息,这通常对用户没有意义。

这应该用作最后的故障保险。它不应取代在整个代码中捕获异常。

【讨论】:

  • Try catch 在你的代码中应该很少见,而不是“贯穿”它。除非你正在做一些不寻常的事情。 stackoverflow.com/questions/14973642/…
  • @Andy 这取决于你如何定义“稀有”。当您在代码中调用您无法控制的方法时(尤其是在涉及 I/O 请求时),您将无法控制是否会引发异常。连接到数据库就是一个完美的例子:如果您在尝试尝试时捕获异常,那么您知道放弃或重试是安全的。但是如果你让这个异常被UnhandledException 事件捕获,那么它就不会知道网络连接失败和内存不足异常之间的区别。
  • 请点击我发布的链接。
  • @Andy 我做了,它支持我所说的。那里接受的答案是“我包含在'try/catch'中:我所知道的所有操作可能不会一直有效(IO 操作、具有潜在零除法的计算......)”
  • 归结为:作为用户,您是否希望看到一条错误消息:“无法访问数据库。您要重试吗?”或“进程因未处理的异常而终止。”
【解决方案2】:

像这样的全局错误处理应该关闭应用程序。 您有来自某处或其他地方的异常,并且该应用处于某种未知状态。

如果你吃掉错误并让用户继续,那么你就无法知道会发生什么。

“标准”方法是记录错误然后关闭

 Application.Current.Shutdown();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-10
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    相关资源
    最近更新 更多