从UnhandledException处理程序调用的异步方法不会等待

时间:2019-12-06 16:04:20

标签: c# .net wpf asynchronous .net-4.7.2

在我的App.xaml.cs中,我创建了一个用于响应AppDomain.CurrentDomain.UnhandledException事件的处理程序。

在处理程序中,我需要调用一个异步方法,该方法发送有关该错误的电子邮件报告。因此,我正在等待该方法,并且在其中等待Net.Mail.SmtpClient.SendMailAsync()

但这是行不通的-当控件到达第二次等待时(恰好在实际发送之前),应用程序退出。

当我摆脱所有异步并使用同步替代方法Net.Mail.SmtpClient.Send()时,电子邮件将正确发送。

似乎没有其他异常在处理程序中抛出。而且,这似乎不只是Visual Studio调试模式的问题。

是否不可能在UnhandledException处理程序内成功调用异步方法?

更新

我的处理程序方法的签名如下:

private async void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e);

我将处理程序附加到App的构造函数中的事件上,如下所示:

App()
{
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}

1 个答案:

答案 0 :(得分:3)

事件始终为enum。这意味着,如果要使用void,则必须使用await。这就是您在这里看到的问题。

async void作用于不完整的await时,该方法的其余部分计划在等待后完成,并返回。通常,它返回调用者可以等待的Task,但是由于返回类型为Task,因此它什么也不返回。呼叫者无法等待,即使它愿意。通常,这与事件无关,因为事件只是发生“某事”的通知,而触发该事件的原因并不依赖于事件处理程序中正在发生的任何事情。

但是在这种情况下,框架会在事件处理程序返回后关闭应用程序,从而继续前进。因此,由于void返回,因此应用程序关闭而无需等待任务实际完成。

您最好的解决方案是使事件处理程序中的所有内容保持同步。这样可以防止它在您期望的返回之前返回。

“保持一切同步”是指实际上使用同步方法(例如await)。请勿同步等待异步方法,因为该can cause deadlocks