.net - 将 CancellationToken 作为参数传递给 Task.Run 有什么好处?

标签 .net vb.net task task-parallel-library cancellation

显然我意识到它使我能够取消任务,但是这段代码无需将 token 传递给 Task.Run 即可达到相同的效果

有什么实际区别?谢谢。

Dim cts As New CancellationTokenSource
Dim ct As CancellationToken = cts.Token
Task.Run(Sub()
             For i = 1 To 1000
                 Debug.WriteLine(i)
                 ct.ThrowIfCancellationRequested()
                 Threading.Thread.Sleep(10)
             Next
         End Sub)

cts.CancelAfter(500)

VS
Dim cts As New CancellationTokenSource
Dim ct As CancellationToken = cts.Token
Task.Run(Sub()
             For i = 1 To 1000
                 Debug.WriteLine(i)
                 ct.ThrowIfCancellationRequested()
                 Threading.Thread.Sleep(10)
             Next
         End Sub, ct)

cts.CancelAfter(500)

最佳答案

API docs for Task.Run(Action, CancellationToken) 有这样的评论:

If cancellation is requested before the task begins execution, the task does not execute. Instead it is set to the Canceled state and throws a TaskCanceledException exception.



因此,在您的场景中,没有任何实际区别,因为您在发出取消之前等待 500 毫秒。在那段时间内,任务被调度,开始执行,并在发出取消之前多次运行循环,表现为从 ct.ThrowIfCancellationRequested() 抛出的异常。 .
Task.Run(Action) 之间的区别和 Task.Run(Action, CancellationToken)您的示例的此修改版本更明显:
Try
    Dim cts As New CancellationTokenSource
    Dim ct As CancellationToken = cts.Token

    cts.Cancel()

    Dim task As Task = Task.Run(
        Sub()
            Console.WriteLine("Started running your code!")
            ct.ThrowIfCancellationRequested()
            Console.WriteLine("Finished running your code!")
        End Sub, ct)

    task.Wait()

Catch ex As AggregateException
    Console.Error.WriteLine("Caught exception: " & ex.InnerException.Message)
End Try

Console.WriteLine("Done, press Enter to quit.")
Console.ReadLine()

在这种情况下,Task.Run安排任务运行,但还将取消 token 与该任务相关联。当我们调用 task.Wait() ,在线程池执行任务之前,它会检查取消 token 并注意到已在该 token 上发出取消,因此它决定在执行任务之前取消。所以输出是:
Caught exception: A task was canceled.
Done, press Enter to quit.

如果您改为替换:End Sub, ct)End Sub) ,然后线程池不知道取消 token ,因此即使您发出了取消,它也会继续执行任务,然后您的任务代码本身会检查取消。所以输出是:
Started running your code!
Caught exception: The operation was canceled.
Done, press Enter to quit.

(您可以看到,这两种情况下的异常消息也略有不同。)

总之,将取消 token 提供给 Task.Run方法允许线程池本身在线程池有机会执行任务之前知道任务是否被取消。这允许线程池通过甚至不费心开始运行任务来节省时间和资源。

关于.net - 将 CancellationToken 作为参数传递给 Task.Run 有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48312544/

相关文章:

.net - 使用 WiX 将程序集放入 GAC 和安装路径

c# - 如何从 pfx/cer 创建 snk?

c# - 托管*稳定* WCF MSMQ Windows 服务的正确方法

VB Razor 中 <script> 元素中的 Javascript 代码

c# - ASP.Net MVC 中长时间运行的进程

c# - 通过 COM 互操作调用线程

C# - 具有特定持续时间的 TcpClient 异步连接

.net - Powershell:管道输入到通过调用运算符执行的命令

vb.net - 如何在 VB.NET 中使用过时的方法实现接口(interface)而不抑制警告?

c# - Double.Parse 没有给出正确的结果