不会等待从 UnhandledException 处理程序调用的异步方法
Async methods called from UnhandledException handler don't get awaited
在我的 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;
}
事件总是 void
。这意味着如果你想使用await
,你必须使用async void
。这就是您在此处看到的问题的原因。
当await
作用于未完成的Task
时,该方法的其余部分在等待后安排完成,并且returns.通常它 return 是调用者可以等待的 Task
,但由于 return 类型是 void
,它 return 什么都不是。调用者不能等待它,即使它想要。通常这不是事件的问题,因为事件只是 "something" 发生的通知,触发事件的任何内容都不依赖于事件处理程序内部发生的任何事情。
但在这种情况下,框架会在事件处理程序 return 之后继续关闭应用程序。因此,自 await
returns 以来,应用程序在没有等待任务实际完成的情况下关闭。
最好的解决方案是让事件处理程序中的所有内容保持同步。这将防止它在您预期之前 returning。
"keep everything synchronous",我的意思是实际使用同步方法(如 Net.Mail.SmtpClient.Send()
)。不要在异步方法上同步等待,因为 can cause deadlocks.
在我的 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;
}
事件总是 void
。这意味着如果你想使用await
,你必须使用async void
。这就是您在此处看到的问题的原因。
当await
作用于未完成的Task
时,该方法的其余部分在等待后安排完成,并且returns.通常它 return 是调用者可以等待的 Task
,但由于 return 类型是 void
,它 return 什么都不是。调用者不能等待它,即使它想要。通常这不是事件的问题,因为事件只是 "something" 发生的通知,触发事件的任何内容都不依赖于事件处理程序内部发生的任何事情。
但在这种情况下,框架会在事件处理程序 return 之后继续关闭应用程序。因此,自 await
returns 以来,应用程序在没有等待任务实际完成的情况下关闭。
最好的解决方案是让事件处理程序中的所有内容保持同步。这将防止它在您预期之前 returning。
"keep everything synchronous",我的意思是实际使用同步方法(如 Net.Mail.SmtpClient.Send()
)。不要在异步方法上同步等待,因为 can cause deadlocks.