ConfigureAwait when not expecting

I have an async method that I use to unload fire work in a few seconds and forget so as not to slow down the loading of my page. This work needs some general tuning and tidying; I want the (fast) installation to choose synchronously if it throws, but I don't want the forced start to run in the ASP context, so I use ConfigureAwait in the bit I expect:

 public Task FireAndForget() { DoSetup(); return FireAndForgetAfterSetup(); } private async Task FireAndForgetAfterSetup() { await AFewSecondsWorthOfWork().ConfigureAwait(false); DoTidyUp(); } protected void btn_Click(object sender, EventArgs e) { FireAndForget(); } 

It seems weird because

  • FireAndForgetAfterSetup doesn't have to worry if it is called from an ASP context, so why should it be the one that calls ConfigureAwait ?
  • If I change my mind and decide that btn_Click should wait for FireAndForget , it already selected the ASP context (?)

Can someone explain to me if I do not understand?

+1
source share
3 answers

ASP.NET synchronization context does not allow you to run work items with the fire and forget function from the request. The runtime actively monitors such things and will try to throw an exception, because these code templates lead to null refs, deadlocks, AVs and other nasty things.

If you absolutely need to get started with fire-and-forget in ASP.NET, consider using WebBackgrounder . It integrates with ASP.NET extensibility points that are designed for this. This way, it will not block the active request, but keep in mind that Stephen warns: it was never guaranteed to be executed at all. If you need guaranteed performance, consider a reliability mechanism such as Service Bus.

+3
source

If your script is about how to perform some (relatively) long-term task at boot time, ASP.NET resolves this script 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 Important Information

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

 RegisterAsyncTask(new PageAsyncTask(MyAsyncMethod)); 

then call Page.ExecuteRegisteredAsyncTasks to start all registered tasks.

Scott Hanselman (kind) (of course) describes why using an event handler, task, or background thread is a bad idea.

This is also described in the What Not to Do in ASP.NET section , what to do instead of in the Asynchronous Pages section.

+1
source

I'm not sure why he did not publish it, but my exact two questions are answered on this blog by Stephen Cleary :

In this example, it is important to note that each β€œlevel” of asynchronous method calls has its own context. DownloadFileButton_Click is launched in the context of the user interface and is called DownloadFileAsync. DownloadFileAsync also started in the context of the user interface, but then went out of context by calling ConfigureAwait (false). The rest of DownloadFileAsync runs in the context of the thread pool. However, when DownloadFileAsync terminates and DownloadFileButton_Click resumes, it resumes in the context of the user interface.

A good rule of thumb is to use ConfigureAwait (false) if you don't know what context you need.

  • In response to my first marker, yes, OK (recommended!) To use ConfigureAwait(false) in library methods that know that they will not use context, because ...
  • ... in response to my second marker point, even if the async library method has dropped the user interface context, the calling method still has its own copy. That way, the calling method could await use the library method and resume it in the context of the user interface ... but this will come to a standstill when that happens.
0
source

All Articles