繁体   English   中英

这里的取消标记有什么用

[英]What is the use of Cancellation token here

我有以下代码块:

using (var cancelSource = new CancellationTokenSource()) 
{
    Task[] tasks = null;

    var cancelToken = cancelSource.Token;
    tasks = new[]
    {
        Task.Run(async () => await ThrowAfterAsync("C", cancelToken, 1000)) //<---
    };
    await Task.Delay(howLongSecs * 1000); // <---
    cancelSource.Cancel();
    await Task.WhenAll(tasks);
}

其中ThrowAfterAsync具有以下内容:

private async Task ThrowAfterAsync(string taskId, CancellationToken cancelToken, int afterMs)
{
    await Task.Delay(afterMs, cancelToken);
    var msg = $"{taskId} throwing after {afterMs}ms";
    Console.WriteLine(msg);
    throw new ApplicationException(msg);
}

Resharper建议我可以将Task.Run()的重载与取消令牌一起使用,如下所示:

Task.Run(async () => await ThrowAfterAsync("C", cancelToken, 1000), cancelToken)

但为什么 ? 在没有取消标记作为参数的情况下,与第一个版本相比,这样做有什么好处?

在这种特定情况下,没有任何意义。 通常,您会按照建议的方式进行操作,因为通过将令牌传递给Task.Run ,即使在操作有机会开始之前取消了令牌,它也可以避免甚至排定调度操作的开始 。您正在创建令牌的情况下,您知道在开始操作时不会取消它。

但是,您不需要将令牌传递给Task.Run的原因是,启动该任务的代码是负责取消令牌的操作 ,因此它知道令牌尚未取消。 通常,您会从其他地方接受令牌,并且您不知道它是否/何时被取消。

所有这一切说,没有理由使用,甚至Task.Run 可言 您可以这样写:

tasks = new[] { ThrowAfterAsync("C", cancelToken, 1000) };

它将具有相同的行为,但是不必为了启动异步操作而不必要地启动新线程。

接下来,由于操作代码的结构,即使操作在此之前完成,您的代码也永远不会在howLongSecs秒内返回 您应该简单地将超时提供给取消令牌源,并让它在正确的时间取消令牌,如果操作在取消发生之前完成,则不会延迟其余方法,因此您的整个方法可以只是写为:

using (var cancelSource = new CancellationTokenSource(Timespan.FromSeconds(howLongSecs))) 
{
    await ThrowAfterAsync("C", cancelToken, 1000)
}

Resharper看到您正在使用的方法( Task.Run )的重载接受CancellationToken ,作用域中具有CancellationToken实例,但是您不使用接受令牌的重载方法。 它不会对您的代码进行任何广泛的分析-就是这么简单。 您可以使用以下代码轻松验证这一点:

class Program {
    static void Main() {
        CancellationToken ct;
        Test("msg"); // will suggest to pass CancellationToken here
    }

    private static void Test(string msg) {

    }

    private static void Test(string msg, CancellationToken ct) {

    }
}

是的,代码本身很奇怪,您根本不需要将异步包装在Task.Run中,但是我不会碰到这一点,因为您只是问为什么Resharper建议这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM