【发布时间】:2019-10-16 05:36:32
【问题描述】:
我有一个使用异步方法连接到 REST API 的应用程序。我几乎在所有连接到 API 的地方都使用 async/await 进行了设置,但是我有一个问题和一些我不完全理解的奇怪行为。我想做的只是在程序关闭时在某些情况下返回许可证。这是由窗口关闭事件启动的;事件处理程序如下:
async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
...other synchronous code...
//Check for floating licensing
if (KMApplication.License != null && KMApplication.License.Scope != Enums.LicenseScope.Standalone)
{
for (int i = 0; i < 3; i++)
{
try
{
await KMApplication.License.ShutDown(KMApplication.Settings == null
? Enums.LicenseReturnModes.PromptOnShutdown
: KMApplication.Settings.LicenseReturnMode)
.ConfigureAwait(false);
break;
}
catch (Exception ex)
{
_logger.Warn("Exception in license release, attempt " + i, ex);
}
}
}
await KMApplication.ApiService.Disconnect().ConfigureAwait(false);
_logger.Info("Shutdown Complete");
Application.Current?.Shutdown();
}
当它运行时,我可以在调试器中单步执行,它会进入第一个许可证关闭调用,这是第一个等待异步调用的调用。然后,当我按 F10 进入下一行代码时,它就会关闭并消失。我验证了应该在该行中发生的许可证发布正在发生,因此它似乎运行到该行的完成,但随后关闭或崩溃或其他东西。我还查看了日志,它永远不会到达Shutdown Complete 行,我也不相信它会到达ApiService.Disconnect。
我还尝试使用Task.Run(() => ...the method...).GetAwaiter().GetResult() 将其作为同步方法运行,但这只会在第一次调用时出现死锁。
我该如何处理并让它运行异步发布,等待它完成,然后关闭?
【问题讨论】:
-
async void不会等待方法完成,因为它是void而不是Task。当然,对于 WinForms 中的事件,不能使用async Task。可能的情况:该方法被触发,然后您的应用程序关闭(因为它不等待)。完成后您可能需要延迟关机。 -
是的,因为它是事件处理程序,我无法做到
async Task,因为它与我正在努力解决的签名不匹配。我真正的困惑是它确实关闭了,但关闭是在 log 方法之后调用的,它永远不会被调用...... -
关闭时的异步流听起来很奇怪。当第一个异步启动时,UI 线程返回到消息泵处理并有效地关闭窗口。
-
您是否尝试过取消活动(通过
CancelEventArgs)?无论如何,您的处理程序都会明确关闭应用程序。您可能需要设置一个标志以确保您不会陷入无限循环。 -
我没有尝试取消活动,但我只是这样做了,没有任何改变。我同意关闭时的异步听起来有点奇怪,但我不知道该怎么做。我希望程序在用户关闭时返回许可证,这是一个异步方法,因为它是一个 http 调用来执行它...
标签: c# .net wpf asynchronous