The following reduced example generates this compiler warning:
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.
public class TaskInterlockedExchangeTest
{
private Task _Task;
public async Task DoSomething()
{
Interlocked.Exchange(ref _Task, null);
await _Task;
}
}
The warning is raised on the line with the Interlocked.Exchange
call. As far as I'm aware Interlocked.Exchange
is not async
so why on earth is the compiler triggering this warning? Right now this doesn't make any sense to me, so what am I missing?
We do treat warnings as errors so I'm trying to figure out how to fix this (short of disabling the warning around the offending code which I would only see as last resort).
This happens on VS2013 (update 5).
Update
I just discovered that the following avoids the warning:
public class TaskInterlockedExchangeTest
{
private Task _Task;
public async Task DoSomething()
{
var t = Interlocked.Exchange(ref _Task, null);
await _Task;
}
}
So simply assigning the result to a local variable is sufficient.
You're calling the generic overload of Interlocked.Exchange
:
public static T Exchange<T>(ref T location1, T value)
where T : class
Which means the result of the call is a Task
. The warning works as designed. It sees you're calling a function which returns a Task
, so is potentially asynchronous, but you don't await
its result.
The line:
Interlocked.Exchange(ref _Task, null);
Means the following:
_Task
with null
Interlocked.Exchange
) The following line:
await _Task;
most probably is the equivalent of:
await null;
And will go boom .
I say most probably , since there's a tiny possibility another thread wrote something into _Task
, and you're going to await
that.
I guess the real code you wanted to write is the following:
public async Task DoSomething()
{
var task = Interlocked.Exchange(ref _Task, null);
if (task != null)
await task;
}
Or, with .NET 4.6:
public async Task DoSomething()
=> await (Interlocked.Exchange(ref _Task, null) ?? Task.CompletedTask);
You may even get rid of the async
:
public Task DoSomething()
=> Interlocked.Exchange(ref _Task, null) ?? Task.CompletedTask;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.