Question

I'm trying to understand the reason why is it bad to do: (notice, context here is asp.net, regardless the plain reason that async void can't be tracked)

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

Well , after investigating a bit I saw few different reasons :

  • Damian Edwards Says here that:

    Async void event handlers in web forms are only supported on certain events, as you've found, but are really only intended for simplistic tasks. We recommend using PageAsyncTask for any async work of any real complexity.

  • Levi Says here that:

    Async events in web applications are inherently strange beasts. Async void is meant for a fire and forget programming model. This works in Windows UI applications since the application sticks around until the OS kills it, so whenever the async callback runs there is guaranteed to be a UI thread that it can interact with. In web applications, this model falls apart since requests are by definition transient. If the async callback happens to run after the request has finished, there is no guarantee that the data structures the callback needs to interact with are still in a good state. Thus why fire and forget (and async void) is inherently a bad idea in web applications.

    That said, we do crazy gymnastics to try to make very simple things like Page_Load work, but the code to support this is extremely complicated and not well-tested for anything beyond basic scenarios. So if you need reliability I’d stick with RegisterAsyncTask.

  • This site says:

    As we know our page life cycle has a set of events that gets fired in a predefined order and next event will be fired only when the last event completes. So if we use the above way of async Page_Load, this event will be fired during page life cycle event once it reaches to async, current thread gets free and a another thread got assigned to complete the task asynchronously, but the ASP.NET cannot execute the next event in life cycle because Page_Load has not been completed yet. And underlying synchronization context waits till the asynchronous activity completes. Then only the next event of page lifecycle will be fired which makes the whole process in synchronous mode only.

  • This site says

    when the return type is void, the caller might assume the method is complete by the time it returns. This problem can crop up in many unexpected ways. It’s usually wrong to provide an async implementation (or override) of a void-returning method on an interface (or base class). Some events also assume that their handlers are complete when they return.

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

Question :

What is the glory/true reason for which we shouldn't write public async void Page_Load(object sender, EventArgs e) ?


nb, I also don't know why it is a problem since 4.5 does use the UseTaskFriendlySynchronizationContext which its aim is to support:

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

Was it helpful?

Solution

The articles you link to make the reasons pretty clear. Don't use it because it isn't reliable beyond the most basic of scenarios. There is only so much async tracking trickery we can pull in the synchronization context on async void methods. We did work to make those basic scenarios work, but our general guidance is to avoid using them and instead explicitly register async work.

OTHER TIPS

I haven't verified this, but I think it's OK to use async void Page_Load(...) in ASP.NET 4.5 WebForms, for as long as the page has <%@ Page Async="true" ... %> declaration.

I think so based on the implementation of AspNetSynchronizationContext.OperationStarted, which is called when any async void method is invoked on a thread with AspNetSynchronizationContext. Here's a 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 HTTP request processing isn't going to be completed until all pending operations have completed, including async void ones.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top