C# 为什么是联锁的。交换触发警告CS4014?
以下简化示例生成此编译器警告: 警告CS4014:由于未等待此调用,因此当前方法的执行将在调用完成之前继续。考虑将“Acess”运算符应用到调用的结果。< /P> 在C# 为什么是联锁的。交换触发警告CS4014?,c#,visual-studio-2013,task-parallel-library,compiler-warnings,C#,Visual Studio 2013,Task Parallel Library,Compiler Warnings,以下简化示例生成此编译器警告: 警告CS4014:由于未等待此调用,因此当前方法的执行将在调用完成之前继续。考虑将“Acess”运算符应用到调用的结果。< /P> 在联锁的线路上发出警告。交换呼叫。就我所知,它不是async,那么编译器究竟为什么会触发这个警告呢?现在这对我来说没有任何意义,那么我错过了什么呢 我们确实将警告视为错误,因此我试图找出如何解决此问题(除了禁用针对违规代码的警告,我将其视为最后手段) 这发生在VS2013上(更新5) 更新 我刚刚发现以下内容避免了警告: public
联锁的线路上发出警告。交换
呼叫。就我所知,它不是async
,那么编译器究竟为什么会触发这个警告呢?现在这对我来说没有任何意义,那么我错过了什么呢
我们确实将警告视为错误,因此我试图找出如何解决此问题(除了禁用针对违规代码的警告,我将其视为最后手段)
这发生在VS2013上(更新5)
更新
我刚刚发现以下内容避免了警告:
public class TaskInterlockedExchangeTest
{
private Task _Task;
public async Task DoSomething()
{
var t = Interlocked.Exchange(ref _Task, null);
await _Task;
}
}
因此,只需将结果赋给局部变量就足够了。您正在调用的是Interlocked.Exchange的函数:
public static T Exchange<T>(ref T location1, T value)
where T : class
指以下各项:
public async Task DoSomething()
{
var task = Interlocked.Exchange(ref _Task, null);
if (task != null)
await task;
}
- 将
\u任务中的内容替换为null
- 抛出上一个值(作为
Interlocked.Exchange
的返回值提供给您)
以下一行:
await _Task;
很可能相当于:
await null;
而且会爆炸
我说的很有可能,因为有一个很小的可能性,另一个线程在\u 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;
Exchange返回任务,请尝试调用另一个从async
方法返回任务的方法,可能会出现相同的警告。您忽略了Interlocked
的返回值,它是任务
。停止忽略它,警告就会消失:)另外,您(很可能)正在等待null
。。。您可能是指var task=Interlocked.Exchange(ref\u task,null);如果(task!=null)等待任务代码>@Luaan提醒自己:永远要学究气,所以:-)我“修正”了上面的评论;)@Lucastzesniewski:这只是一个再现警告的最小示例,而不是实际的生产代码。我知道在这个示例中,\u Task
是null
。这是复制警告所需的最小代码。嗯,我明白了。因此,一个方法返回的Task
被认为是潜在的异步(即使没有关于Interlocked.Exchange是异步的)就足够了。无论如何,只需将返回值赋给局部变量(而不实际使用它)就可以避免出现警告。@ChrisWue完全正确。但我想说,当应用于泛型返回类型时,这种逻辑是有争议的,正如您的示例所示。@Lucastzesniewski我同意,所以我创建了。
public Task DoSomething()
=> Interlocked.Exchange(ref _Task, null) ?? Task.CompletedTask;