语言

CA2016:将 CancellationToken 参数转发至使用该参数的方法

属性 值
类型名称 ForwardCancellationTokenToInvocations
规则 ID CA2016
标题 将 CancellationToken 参数转发到使用该参数的方法
类别 可靠性
修复是导致破坏性更改还是非破坏性更改 非中断
在 .NET 10 中默认启用 作为一种建议
适用的语言 C# 和 Visual Basic

原因

此规则查找可以接受 CancellationToken 参数但不传递任何参数的方法调用,并建议将父方法的 CancellationToken 转发给它们。

规则说明

此规则分析将 CancellationToken 作为其最后一个参数的方法定义,然后分析其主体中调用的所有方法。 如果任何方法调用可以接受 CancellationToken 作为最后一个参数,或者具有将 CancellationToken 作为最后一个参数的重载,此规则将建议改用该选项,以确保将取消通知传播到可以侦听它的所有操作。

注意

在 CancellationToken 类型可用的所有 .NET 版本中,规则 CA2016 都可用。 关于适用的版本,请参阅 CancellationToken“适用于”部分。

如何解决违规

可以手动修复冲突,也可以使用 Visual Studio 中提供的代码修复功能。 在方法调用旁出现的灯泡图标上悬停光标,并选择建议的更改。

下面的示例演示了两个建议的更改:

规则 CA2016 - 将 CancellationToken 参数转发到接受此参数的方法

如果您不关心将已取消操作的通知传递给下层方法调用,抑制对此规则的违例是安全的。 也可以在 C# 中显式传递 default(在 Visual Basic 中为 Nothing)或 None,以抑制规则违规。

此规则可以检测各种违规。 下面的示例演示了此规则可检测的情况:

示例 1

此规则建议将 ct 参数从 MyMethod 转发到 MyMethodWithDefault 调用,因为该方法定义了一个可选的令牌参数:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithDefault(CancellationToken ct = default)
        {
        }

        public static void MyMethod(CancellationToken ct)
        {
            MyMethodWithDefault();
        }
    }
}

解决方法:

转发 ct 参数:

public static void MyMethod(CancellationToken ct)
{
    MyMethodWithDefault(ct);
}

如果不关心是否要将取消通知转发给下层调用,可以:

显式传递 default:

public static void MyMethod(CancellationToken ct)
{
    MyMethodWithDefault(default);
}

或显式传递 CancellationToken.None:

public static void MyMethod(CancellationToken ct)
{
    MyMethodWithDefault(CancellationToken.None);
}

示例 2

此规则建议将 ct 参数从 MyMethod 转发到 MyMethodWithOverload 调用,因为该方法具有接受 CancellationToken 参数的重载:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithOverload()
        {
        }

        public static void MyMethodWithOverload(CancellationToken ct = default)
        {
        }

        public static void MyMethod(CancellationToken ct)
        {
            MyMethodWithOverload();
        }
    }
}

解决方法:

转发 ct 参数:

public static void MyMethod(CancellationToken ct)
{
    MyMethodWithOverload(ct);
}

如果不在意是否将取消通知传递给下层调用,可以选择以下其中一种方法:

明确传递 default:

public static void MyMethod(CancellationToken ct)
{
    MyMethodWithOverload(default);
}

或显式传递 CancellationToken.None:

public static void MyMethod(CancellationToken ct)
{
    MyMethodWithOverload(CancellationToken.None);
}

不冲突的示例

父方法中的 CancellationToken 参数不在最后位置:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithDefault(CancellationToken ct = default)
        {
        }

        public static void MyMethod(CancellationToken ct, int lastParameter)
        {
            MyMethodWithDefault();
        }
    }
}

默认方法中的 CancellationToken 参数不在最后位置:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithDefault(CancellationToken ct = default, int lastParameter = 0)
        {
        }

        public static void MyMethod(CancellationToken ct)
        {
            MyMethodWithDefault();
        }
    }
}

重载方法中的 CancellationToken 参数不在最后位置:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithOverload(int lastParameter)
        {
        }
        public static void MyMethodWithOverload(CancellationToken ct, int lastParameter)
        {
        }

        public static void MyMethod(CancellationToken ct)
        {
            MyMethodWithOverload();
        }
    }
}

父方法定义了多个 CancellationToken 参数:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithDefault(CancellationToken ct = default)
        {
        }

        public static void MyMethod(CancellationToken ct1, CancellationToken ct2)
        {
            MyMethodWithDefault();
        }
    }
}

具有默认值的方法定义了多个 CancellationToken 参数:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithDefault(CancellationToken ct1 = default, CancellationToken ct2 = default)
        {
        }

        public static void MyMethod(CancellationToken ct)
        {
            MyMethodWithDefault();
        }
    }
}

方法重载定义了多个 CancellationToken 参数:

using System.Threading;

namespace ConsoleApp
{
    public static class MyTestClass
    {
        public static void MyMethodWithOverload(CancellationToken ct1, CancellationToken ct2)
        {
        }

        public static void MyMethodWithOverload()
        {
        }

        public static void MyMethod(CancellationToken ct)
        {
            MyMethodWithOverload();
        }
    }
}

抑制警告

如果只想抑制单个冲突,请将预处理器指令添加到源文件以禁用该规则,然后重新启用该规则。

#pragma warning disable CA2016
// The code that's violating the rule is on this line.
#pragma warning restore CA2016

若要对文件、文件夹或项目禁用该规则,请在none中将其严重性设置为 。

[*.{cs,vb}]
dotnet_diagnostic.CA2016.severity = none

有关详细信息,请参阅如何禁止显示代码分析警告。