将CancerationToken作为参数传递给Task.Run有什么好处? [英] Whats the benefit of passing a CancellationToken as a parameter to Task.Run?

查看:47
本文介绍了将CancerationToken作为参数传递给Task.Run有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

显然,我意识到它使我能够取消任务,但此代码无需将令牌传递到Task中即可达到相同的效果。运行

实际区别是什么?谢谢。

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)备注:

如果在任务开始执行之前请求取消,则任务不会执行。而是将其设置为已取消状态,并引发TaskCanceledException异常。

所以在您的场景中,没有任何实际区别,因为您在发出取消命令之前等待了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安排任务运行,但也将取消令牌与该任务相关联。当我们调用task.Wait()时,在线程池执行任务之前,它会检查取消令牌,并通知已经在该令牌上发出了取消令牌,因此它决定在执行任务之前取消。因此输出为:

Caught exception: A task was canceled.
Done, press Enter to quit.

如果将:End Sub, ct)替换为End Sub),则线程池不知道取消令牌,因此即使您发出了取消令牌,它也会在任务代码本身检查取消之前继续执行任务。因此输出为:

Started running your code!
Caught exception: The operation was canceled.
Done, press Enter to quit.

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

总而言之,向Task.Run方法提供取消令牌允许线程池本身在线程池有机会执行任务之前知道任务是否被取消。这使线程池甚至无需开始运行任务就可以节省时间和资源。

这篇关于将CancerationToken作为参数传递给Task.Run有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆