以下简化示例会生成此编译器警告:
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;
}
}
警告是在调用 Interlocked.Exchange
的行上发出的。据我所知Interlocked.Exchange
不是 async
那么为什么编译器会触发这个警告呢?现在这对我来说没有任何意义,所以我错过了什么?
我们确实将警告视为错误,所以我试图弄清楚如何解决这个问题(除了禁用围绕有问题的代码的警告,我只会将其视为最后的手段)。
这发生在 VS2013(更新 5)上。
更新
我刚刚发现以下内容避免了警告:
public class TaskInterlockedExchangeTest
{
private Task _Task;
public async Task DoSomething()
{
var t = Interlocked.Exchange(ref _Task, null);
await _Task;
}
}
所以简单地将结果分配给局部变量就足够了。
最佳答案
您正在调用 generic overload Interlocked.Exchange
:
public static T Exchange<T>(ref T location1, T value)
where T : class
这意味着调用的结果是一个任务
。警告按设计工作。它发现您正在调用一个返回 Task
的函数,因此可能是异步的,但您不会等待
它的结果。
行:
Interlocked.Exchange(ref _Task, null);
含义如下:
- 将
_Task
中的内容替换为null
- 抛出之前的值(给你作为
Interlocked.Exchange
的返回值)
下面一行:
await _Task;
很可能相当于:
await null;
而且会繁荣。
我说最有可能,因为极有可能另一个线程将某些内容写入_Task
,而您将等待
。
我想你真正想写的代码如下:
public async Task DoSomething()
{
var task = Interlocked.Exchange(ref _Task, null);
if (task != null)
await task;
}
或者,对于 .NET 4.6:
public async Task DoSomething()
=> await (Interlocked.Exchange(ref _Task, null) ?? Task.CompletedTask);
你甚至可以去掉 async
:
public Task DoSomething()
=> Interlocked.Exchange(ref _Task, null) ?? Task.CompletedTask;
关于c# - 为什么 Interlocked.Exchange 触发警告 CS4014?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35417106/