我有一个问题如何等待WPF生命周期方法中的异步方法(使用Caliburn-Micro框架)(例如OnActivate,OnInitialized,OnExit - 它直接绑定到 Application.Exit 事件)
这篇文章准确地描述了我的问题:http://mark.mymonster.nl/2013/07/10/donrsquot-make-your-application-lifetime-events-async-void(现在我正在考虑使用本文中的解决方案,但第一次看起来有点矫枉过正)
我需要在OnExit hanlder中等待一些异步方法,所以我把它作为异步。它有效。的种类。 我不明白为什么?? ,但是在调用Application.Exit事件时,它会以某种方式等待,直到方法完成,即使处理程序是异步void。 你能解释一下这是怎么回事吗?这样安全吗?或者只是自信? Async void只能用于顶级事件,是这种情况吗?
我查看了System的代码。绑定看起来像这样:
public event EventHandler Exit
{
add
{
XcpImports.CheckThread();
this.AddEventListener(DependencyProperty.RegisterCoreProperty(20053U, (Type) null), (Delegate) value);
}
remove
{
XcpImports.CheckThread();
this.RemoveEventListener(DependencyProperty.RegisterCoreProperty(20053U, (Type) null), (Delegate) value);
}
}
这真是神秘,我无法通过调用此事件来了解.net框架中发生了什么。
奇怪的是,当我不使用 ConfigureAwait(false)时,在处理程序中调用等待Task.Delay(1)会导致死锁。所以我想说在.net代码深处使用了 .Wait()。
注意:当我按照预期制作OnActivate,OnInitialized处理程序async时,页面不会等到处理程序完成。
谢谢你的回答!
答案 0 :(得分:10)
理论上,框架可以检测async void
的使用并等到async void
方法返回。我在article on SynchronizationContext
中描述了详细信息。 AFAIK,ASP.NET是唯一一个等待async void
处理程序的内置框架。
WPF 不对async void
方法有任何特殊处理。因此,您的退出处理程序正在完成的事实只是巧合。我怀疑你await
的操作已经完成或非常快,这使得你的处理程序可以同步完成。
尽管如此,我不推荐您引用的文章中的解决方案。相反,处理窗口的Closing
事件,启动您需要执行的任何异步保存,并取消关闭命令(并考虑立即隐藏窗口)。异步操作完成后,再次关闭窗口(并允许它关闭此时间)。我使用这种模式进行异步窗口级“关闭”动画。
我无法重现您描述的僵局。我创建了一个新的.NET 4.5 WPF应用程序,并添加了一个退出处理程序:
private async void Application_Exit(object sender, ExitEventArgs e)
{
await Task.Delay(1);
}
但没有观察到僵局。事实上,即使使用Task.Yield
,在执行await
之后也没有任何内容,这就是我所期望的。