为什么Interlocked.Exchange触发警告CS4014?

时间:2016-02-15 19:01:47

标签: c# visual-studio-2013 task-parallel-library compiler-warnings

以下简化示例生成此编译器警告:

  

警告CS4014:由于未等待此呼叫,因此在呼叫完成之前将继续执行当前方法。考虑应用“等待”#39;运算符到调用的结果。

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;
    }
}

所以简单地将结果分配给局部变量就足够了。

1 个答案:

答案 0 :(得分:6)

您正在调用Interlocked.Exchange的{​​{3}}:

public static T Exchange<T>(ref T location1, T value)
    where T : class

这意味着通话的结果是Task。警告按设计工作。它会看到您正在调用一个返回Task的函数,因此可能是异步的,但您不会await其结果。

该行:

Interlocked.Exchange(ref _Task, null);

表示以下内容:

  • 用[{1}}
  • 替换_Task中的内容
  • 丢弃先前的值(作为null的返回值
  • 给出)

以下一行:

Interlocked.Exchange

最有可能相当于:

await _Task;

并将热潮

我说很可能是,因为其他线程在await null; 中写了一些内容的可能性微乎其微,而且你要去_Task那个。{ / p>

我想您想写的真实代码如下:

await

或者,使用.NET 4.6:

public async Task DoSomething()
{
    var task = Interlocked.Exchange(ref _Task, null);

    if (task != null)
        await task;
}

你甚至可以摆脱public async Task DoSomething() => await (Interlocked.Exchange(ref _Task, null) ?? Task.CompletedTask);

async