Whats the benefit of passing a CancellationToken as a parameter to Task.Run?(将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有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:将CancerationToken作为参数传递给Task.Run有什么好处?


- 如何用自己压缩一个 IEnumerable 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 输入按键事件处理程序 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01