2017-01-16 44 views
3

我通常编写web服务器,起初我认为必须有连续的方法链返回任务,所以填满堆栈可能会询问数据库是否完成。c#如何处理异步void

最近我看到WPF的代码,这不类似的东西:

public async void Execute(object parameter) 
    { 
     await ExecuteAsync(parameter); 
    } 

在事件处理函数调用。用户界面似乎是响应式的,所以我想它确实有效。它是如何工作的?这是如何转化为aspnet的?

回答

6

Async void仅用于事件处理程序/委托可比性。 Execute是一个事件回调,可能来自DelegateCommand或类似的事件。

它的工作方式是,它的处理方式与您返回Task的函数完全相同,但调用者从未在返回的任务上调用await

在ASP.NET你可能永远不会使用异步无效,改为使用控制器,公开方法返回一个Task<ActionResult>,使用HostingEnviorment.QueueBackgroundWorkItem,或者使用在在一个情况,其中Page.RegisterAsyncTask你会使用async void包裹起来功能在正常的桌面编程中。

public void Page_Load(object sender, EventArgs e) 
{ 
    RegisterAsyncTask(new PageAsyncTask(LoadSomeData)); 
} 
+0

当我不等待任务时会发生什么? – user2029276

+1

@ user2029276 asp.net子系统不知道该任务,并可能在该功能完成执行之前拆除该网站的应用程序域,导致您告诉该功能做的工作丢失并且从未完成。你可以在WPF中摆脱这种情况的原因是你的AppDomain在用户使用这个程序的时候不会被随意拆除,只要程序运行在AppDomain上。一个不活跃的用户在一个asp.net网站上可能会有一个AppDomain被拆除,甚至没有注意到它发生。 –

7

我解释async void方法的工作原理 - 以及为什么他们应该避免 - 在我Best Practices in Asynchronous Programming文章。

async voidasync Task具有相同的语义,例外情况除外。一个async void方法将在该方法开始时捕获当前的SynchronizationContext,并且该方法的任何异常都将被捕获并直接在该捕获的上下文中引发。在最常见的情况下,这会导致应用程序级异常,通常是崩溃。有些人称async void方法为“即忘即忘”,但由于其特殊的行为,我更喜欢“火灾和碰撞”。 :)

“避免异步无效”是一般准则,有一个值得注意的例外:事件处理程序(或逻辑上是事件处理程序的项目,如ICommand.Execute实现)。

它是如何工作的?这是如何转化为aspnet的?

它的工作方式与其他async方法一样。主要的平台区别在于当async方法完成时,UI线程不需要知道。 ASP.NET需要知道它知道何时发送请求,但UI不需要知道方法何时完成。所以async void的作品。这仍然是最好的避免,因为调用代码通常确实需要知道它何时完成。