Consider:
using System.Threading.Tasks; class Program { static void Main(string[] args) { C c = new C(); c.FooAsync(); // warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. ((I)c).FooAsync(); // No warning } } class C : I { public async Task FooAsync() { } } interface I { Task FooAsync(); }
If I call the async method directly on the c
object, I get a compiler warning. There's potentially a bug here, so I'm glad for the warning.
However, if I make the same call on an interface method, I get no warning. It would be easy to let a bug slip past in this code.
How can I ensure that I don't make this mistake? Is there a pattern I can apply to protect myself?
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
await releases the current thread, but NOT to the thread pool. The UI thread doesn't come from the thread pool. If you run asynchronous method, e.g. ExecuteScalarAsync without async, await keywords, then this method will run asynchronously no matter what. The calling thread won't be affected .
When a asynchronous method is executed, the code runs but nothing happens other than a compiler warning. What is most likely causing the method to not return anything? (A) The return yield statement is missing at the end of the method.
The await keyword, by contrast, is non-blocking, which means the current thread is free to do other things during the wait.
Main is not async, so it can't use await
. This seems to confuse the compiler messages slightly. If you put the calls into an actual async method;
static void Main(string[] args) { Task.Run(async () => { C c = new C(); c.FooAsync(); ((I) c).FooAsync(); }); }
...both will warn.
Line 10: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Line 11: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
EDIT: It seems like all methods that return Task
inside async methods will warn unless you await or assign them; note that we're working with the interface that doesn't even mention async;
interface I { Task FooAsync(); } static void Main(string[] args) { I i = null; i.FooAsync(); // Does not warn // await i.FooAsync(); // Can't await in a non async method var t1 = i.FooAsync(); // Does not warn Task.Run(async () => { i.FooAsync(); // Warns CS4014 await i.FooAsync(); // Does not warn var t2 = i.FooAsync(); // Does not warn }); }
The logic for this warning seems to be:
async
method, warn whenever a Task
-returning method is called, but the result is ignoredasync
) method, warn whenever a Task
-returning async
method is called, but the result is ignoredFor example, look at this (nonsensical) code:
Task NonAsyncMethod() { AsyncMethod(); // warnig NonAsyncMethod(); // no warning return null; // to make the code compile } async Task AsyncMethod() { AsyncMethod(); // warning NonAsyncMethod(); // warning }
This is why you're not getting the warning with the interface: the interface method isn't (and can't) be marked as async
.
I think the reason for this is that in old, pre-async
code, it's common to for example call task.ContinueWith()
and ignore its result. If the warning was reported in this case too, relatively large amount of old correct code would suddenly become warnings.
A warning should be output when there is a large likelihood of a bug. I think that the cases that are reported are much more likely to be bugs than the case which isn't. So to me, this behavior make sense.
If you want to make sure you don't make this mistake, be careful about calling Task
-returning methods from non-async
code.
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