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?
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.
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.
%d. a decimal integer (assumes base 10) %i. a decimal integer (detects the base automatically)
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:
*The implementation of SomeTaskMethod
, the underlying framework, the SynchronizationContext and other factors might and will cause different outcomes for each of the above methods.
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With