CA2007:不直接等待任务

属性
规则 ID CA2007
标题 不直接等待任务
类别 可靠性
修复是中断修复还是非中断修复 非中断
在 .NET 8 中默认启用

原因

异步方法会直接等待Task

规则说明

异步方法直接等待 Task 时,延续任务通常会出现在创建任务的同一线程中,具体取决于异步上下文。 此行为可能会降低性能,并且可能会导致 UI 线程发生死锁。 请考虑调用 Task.ConfigureAwait(Boolean) 以表示延续任务意图。

如何解决冲突

若要解决冲突,请在等待的 Task 上调用 ConfigureAwait。 可以为 continueOnCapturedContext 参数传递 truefalse

  • 对任务调用 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 应用程序中编写代码时,默认情况下没有 SynchronizationContextTaskScheduler,原因是 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

另请参阅