『技术群里聊些啥』Task 不是你想 Cancel,想 Cancel 就能 Cancel

前言

在群里看到有人问如何取消这个 Task 的执行:

fcfc3f78d50bf90f6f4e76d2e55afd7c.png

实际上这并不会取消S1eepMode1方法的执行:

a79ba5572524a1ab1bb9225d97e66af0.png

这是为什么呢?

原因

首先,让我们看看s_cts.Cancel()都做了啥:

public void Cancel() => Cancel(false);

public void Cancel(bool throwOnFirstException)
{
    ThrowIfDisposed();
    NotifyCancellation(throwOnFirstException);
}

private void NotifyCancellation(bool throwOnFirstException)
{
    // If we're the first to signal cancellation, do the main extra work.
    if (!IsCancellationRequested 
&& Interlocked.CompareExchange(ref _state, NotifyingState, NotCanceledState) == NotCanceledState)
    {
        ...
    }
}

实际上,Cancel方法仅仅是将变量_state的值改为NotifyingState

Task.Run传递s_cts.Token又有什么用呢?

public static Task<TResult> Run<TResult>(Func<Task<TResult>?> function, CancellationToken cancellationToken)
{
    if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);

    // Short-circuit if we are given a pre-canceled token
    if (cancellationToken.IsCancellationRequested)
        return Task.FromCanceled<TResult>(cancellationToken);

    ...
}

原来,是在创建 Task 前先检查令牌是否已经Cancel,以便快速终止。

那么,到底怎么才能Cacel已创建的Task呢?

实现

其实,Task.Run的方法实现已经告诉我们正确的解决方案,那就是判断cancellationToken.IsCancellationRequested:

public static async Task S1eepMode1(CancellationToken cancellationToken)
{
    while (true)
    {
        if (cancellationToken.IsCancellationRequested)
            return;

        ...
    }
}

另外,也可以采取抛出异常的方式:

public static async Task S1eepMode1(CancellationToken cancellationToken)
{
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        ...
    }
}

示例应用程序并不会捕获到这个异常,相关问题可以看我以前的文章《如何保证执行异步方法时不会遗漏 await 关键字

结论

在创建 Task 时请记住,即使你执行了令牌取消操作,也并不意味着 Task 会停止运行。

添加微信号【MyIO666】,邀你加入技术交流群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值