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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…