CA2007:不直接等待任务
属性 | 值 |
---|---|
规则 ID | CA2007 |
标题 | 不直接等待任务 |
类别 | 可靠性 |
修复是中断修复还是非中断修复 | 非中断 |
在 .NET 8 中默认启用 | 否 |
原因
规则说明
异步方法直接等待 Task 时,延续任务通常会出现在创建任务的同一线程中,具体取决于异步上下文。 此行为可能会降低性能,并且可能会导致 UI 线程发生死锁。 请考虑调用 Task.ConfigureAwait(Boolean) 以表示延续任务意图。
如何解决冲突
若要解决冲突,请在等待的 Task 上调用 ConfigureAwait。 可以为 continueOnCapturedContext
参数传递 true
或 false
。
对任务调用
ConfigureAwait(true)
与未显式调用 ConfigureAwait 的行为相同。 通过显式调用此方法,可让读取者知道你是有意要对原始同步上下文执行延续任务。对任务调用
ConfigureAwait(false)
可将延续任务安排到线程池,从而避免 UI 线程上出现死锁。 对于与应用无关的库,传递false
是一个好的选择。
示例
下面的代码片段会生成此警告:
public async Task Execute()
{
Task task = null;
await task;
}
若要解决此冲突,请在等待的 Task 上调用 ConfigureAwait:
public async Task Execute()
{
Task task = null;
await task.ConfigureAwait(false);
}
何时禁止显示警告
此警告适用于库,在库中,可能会在任意环境中执行代码,而代码不应对环境或方法的调用方如何调用或等待作出假设。 一般来说,对于代表应用程序代码(而不是库代码)的项目,可完全禁止显示此警告;事实上,在应用程序代码上运行该分析器(例如 WinForms 或 WPF 项目中的按钮单击事件处理程序)很可能会导致执行错误的操作。
如果应将延续任务安排回原始上下文,或者还没有此类上下文,都可禁止显示此警告。 例如,在 WinForms 或 WPF 应用程序中的按钮单击事件处理程序中编写代码时,通常情况下,等待的延续任务应在 UI 线程上运行,因而需要将延续任务安排回原始上下文的默认行为。 另举一例,在 ASP.NET Core 应用程序中编写代码时,默认情况下没有 SynchronizationContext 或 TaskScheduler,原因是 ConfigureAwait
不会实际更改任何行为。
抑制警告
如果只想抑制单个冲突,请将预处理器指令添加到源文件以禁用该规则,然后重新启用该规则。
#pragma warning disable CA2007
// The code that's violating the rule is on this line.
#pragma warning restore CA2007
若要对文件、文件夹或项目禁用该规则,请在配置文件中将其严重性设置为 none
。
[*.{cs,vb}]
dotnet_diagnostic.CA2007.severity = none
有关详细信息,请参阅如何禁止显示代码分析警告。
配置代码以进行分析
使用下面的选项来配置代码库的哪些部分要运行此规则。
可以仅为此规则、为适用的所有规则或为适用的此类别(可靠性)中的所有规则配置所有这些选项。 有关详细信息,请参阅代码质量规则配置选项。
排除 async void 方法
可配置是否要排除不从此规则返回值的异步方法。 要排除这些类型的方法,需将以下键值对添加到项目中的 .editorconfig 文件:
# Package version 2.9.0 and later
dotnet_code_quality.CA2007.exclude_async_void_methods = true
# Package version 2.6.3 and earlier
dotnet_code_quality.CA2007.skip_async_void_methods = true
输出类型
还可以配置此规则要应用的输出程序集种类。 例如,如果仅将此规则应用于生成控制台应用程序或动态链接库的代码(即不是 UI 应用),需将以下键值对添加到项目中的 .editorconfig 文件:
dotnet_code_quality.CA2007.output_kind = ConsoleApplication, DynamicallyLinkedLibrary