ConfigureAwait when not awaiting

醉酒当歌 提交于 2019-12-04 18:13:42

The ASP.NET synchronization context doesn't allow fire-and-forget work items to be kicked off from within a request. The runtime actively monitors such things and will try to generate an exception since these code patterns lead to null refs, deadlocks, AVs, and other nastiness.

If you absolutely need to kick off fire-and-forget work in ASP.NET, consider using WebBackgrounder. It integrates with the ASP.NET extensibility points that are designed to allow for this. So it won't block the active request, but keep in mind Stephen's caveat: it's not ever guaranteed to be executed at all. If you require guaranteed execution, consider a reliability mechanism like Service Bus.

If your scenario is how to execute some (relatively) long-running task during load, ASP.NET allows this scenario through the Page.RegisterAsyncTask method. Scott Hansleman describes how to use it in The Magic of using Asynchronous Methods in ASP.NET 4.5 plus an important gotcha

Essentially, you create an asynchronous method that returns Task and call:

RegisterAsyncTask(new PageAsyncTask(MyAsyncMethod));

then call Page.ExecuteRegisteredAsyncTasks to start executing all registered tasks.

Scott Hanselman does a good job (of course) of describing why using an event handler, Task or background thread is a bad idea.

This is also described in "What Not to do in ASP.NET, What to do instead" in the "Asynchronous Page Events" section

I'm not sure why he didn't post it, but my exact two questions are answered in this blog post by Stephen Cleary:

The important thing to note with this example is that each "level" of async method calls has its own context. DownloadFileButton_Click started in the UI context, and called DownloadFileAsync. DownloadFileAsync also started in the UI context, but then stepped out of its context by calling ConfigureAwait(false). The rest of DownloadFileAsync runs in the thread pool context. However, when DownloadFileAsync completes and DownloadFileButton_Click resumes, it does resume in the UI context.

A good rule of thumb is to use ConfigureAwait(false) unless you know you do need the context.

  • In answer to my first bullet point, yes, it's OK (encouraged!) to use ConfigureAwait(false) in library methods that know they won't use the context, because...
  • ... in answer to my second bullet point, even if the library async method has thrown away the UI context, the calling method still has its own copy. Thus the calling method could await the library method and resume in the UI context... but it's going to deadlock when that happens.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!