Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# allow making an override async?

Tags:

c#

async-await

In C#, when you override a method, it is permitted to make the override async when the original method was not. This seems like poor form.

The problem that makes me wonder is this: I was brought in to assist with a load test problem. At around 500 concurrent users, the login process would break down into a redirect loop. IIS was logging exceptions with the message "An asynchronous module or handler completed while an asynchronous operation was still pending". Some searching led me to think that someone was abusing async void, but my quick searches through the source found nothing.

Sadly, I was searching for async\s*void (regex search) when I should have been looking for something more like async\s*[^T] (assuming Task wasn't fully qualified.. you get the point).

What I later found was async override void onActionExecuting in a base controller. Clearly that had to be the problem, and it was. Fixing that up (making it synchronous for the moment) resolved the problem.

But it left me with a question: Why can you mark an override as async when the calling code could never await it?

like image 722
Peter T. LaComb Jr. Avatar asked Mar 05 '16 17:03

Peter T. LaComb Jr.


People also ask

Why semicolon is used in C?

Semicolons are end statements in C. The Semicolon tells that the current statement has been terminated and other statements following are new statements. Usage of Semicolon in C will remove ambiguity and confusion while looking at the code.

Why do we use hashtag in C?

Application: The ## provides a way to concatenate actual arguments during macro expansion. If a parameter in the replacement text is adjacent to a ##, the parameter is replaced by the actual argument, the ## and surrounding white space are removed, and the result is re-scanned.

What does %D stand for in C?

%d. a decimal integer (assumes base 10) %i. a decimal integer (detects the base automatically)


2 Answers

When the base class (or interface) declares a virtual method that returns a Task, you can override it as long as you return Task. The async keyword is just a hint to the compiler to transform your method into a state machine. Although the compiler does it's black magic on your method, the compiled method still returns a Task.


As for void virtual methods, you can override one without the async keyword (obviously) and start a non-awaited Task within it. That's kind of what happens when you override it with the async keyword and use await in the body. The caller would not await the created Task (since the "original" signature is void). Both cases are similar*:

public override void MyVirtualMethod() {     // Will create a non awaited Task (explicitly)     Task.Factory.StartNew(()=> SomeTaskMethod());   }  public override async void MyVirtualMethod() {     // Will create a non awaited Task (the caller cannot await void)     await SomeTaskMethod();   } 

Stephen Cleary's article has some notes regarding this:

  • Void-returning async methods have a specific purpose: to make asynchronous event handlers possible.
  • You should prefer async Task to async void.

*The implementation of SomeTaskMethod, the underlying framework, the SynchronizationContext and other factors might and will cause different outcomes for each of the above methods.

like image 87
shay__ Avatar answered Sep 18 '22 20:09

shay__


You can override async method because async is not a part of method signature. Actually async allows using await keyword in your method by creating a state machine inside.
You can find more info about async here: http://blog.sublogic.com/2012/05/14/async-isnt-really-part-of-your-method-signature/

like image 23
Kirill Avatar answered Sep 21 '22 20:09

Kirill