Async void event handlers - clarification?

I am trying to understand the reason why this is bad to do: (note, here is the asp.net context, regardless of the simple reason why async void cannot be tracked)

  public async void Page_Load(object sender, EventArgs e) { ... } 

Well, after a little research, I saw several different reasons:

  • Damian Edwards says here that:

    Async void event handlers in web forms are only supported on specific events , as you have found, but are actually intended only to simplify the task. We recommend using PageAsyncTask for any asynchronous operation of any real complexity.

  • Levy says here that:

    Asynchronous events in web applications are inherently strange animals. asynchronous void is for fire and forgets the programming model. This works in Windows UI Applications, as the OS application kills it, so whenever an async callback is executed, it is guaranteed to be a UI thread with which it can interact. In web applications, this model is falling apart, as requests by definition are temporary. If the asynchronous callback starts after the request completes. do not guarantee that data structures must interact with the callback are still in good condition . So why shoot and forget (and void asynchronously) is inherently a bad idea in web applications.

    Nevertheless, we are doing crazy gymnastics to try to do very simple things, for example, Page_Load, but the code supporting it is extremely complex and not sufficiently tested for anything other than the main scenarios. Therefore, if you need reliability Id stick with RegisterAsyncTask.

  • This site says:

    As we know, our page life cycle contains many events that are fired in a predetermined order , and the next event will be fired only when the last event ends. So, if we use the async Page_Load method above, this event will be fired during the page lifecycle event, when it reaches async, the current thread is freed, and the other thread is assigned to complete the task asynchronously , but ASP.NET cannot execute the next event in life cycle because Page_Load is not completed yet . And also the underlying synchronization context waits until asynchronous activity is complete. Then only the next event of the page life cycle will be which makes the whole process only in synchronous mode.

  • This site says

    when the return type is invalid, the caller may assume that the method has completed by the time it returns . This problem can occur in many unexpected ways. Its usually incorrect to provide an asynchronous implementation (or override) of a void-returning method on an interface (or base class). Some events also assume that their handlers are completed when they return .

I see here very different (non-overlapping) reasons.

Question:

What is the glory / true reason why we should not write public async void Page_Load(object sender, EventArgs e) ?


nb, I also don’t know why this is a problem, since 4.5 uses UseTaskFriendlySynchronizationContext , which is to support it :

protected async void Page_Load(object sender, EventArgs e){...}

+7
c # async-await
source share
2 answers

The articles you link to make the reasons pretty clear. Do not use it because it is not reliable outside of most basic scenarios. There are only so many asynchronous tracking tricks that we can use in the synchronization context for asynchronous methods. We really worked to get these basic scenarios to work, but our general guide is to avoid using them and instead register async activity explicitly.

+5
source share

I did not check this one , but I think that using async void Page_Load(...) in ASP.NET 4.5 WebForms is possible if the page has an advertisement <%@ Page Async="true" ... %> .

I think so, based on the implementation of AspNetSynchronizationContext.OperationStarted , which is called when any async void method is called in a thread with AspNetSynchronizationContext . Here is the relevant comment:

  // If the caller tries to kick off an asynchronous operation while we are not // processing an async module, handler, or Page, we should prohibit the operation. 

Apparently, pages with Async="true" do not violate this requirement, and the processing of HTTP requests will not be completed until all incomplete operations have been completed, including async void .

+2
source share

All Articles