C# 如何保证CancellationTokens是最新的?
微软在.NET4中使用了这一C# 如何保证CancellationTokens是最新的?,c#,.net,multithreading,task-parallel-library,cancellation-token,C#,.net,Multithreading,Task Parallel Library,Cancellation Token,微软在.NET4中使用了这一CancellationToken功能 using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { var tokenSource2 = new CancellationTokenSource(); CancellationToken ct = tokenSource2.
CancellationToken
功能
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Factory.StartNew(() =>
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // Pass same token to StartNew.
tokenSource2.Cancel();
// Just continue on this thread, or Wait/WaitAll with try-catch:
try
{
task.Wait();
}
catch (AggregateException e)
{
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
Console.ReadKey();
}
}
但是,如果在一个线程上修改变量,另一个线程可能由于缓存而无法获得修改后的值。既然CancellationToken
在主线程上被取消,那么Task
线程如何确保它正在检查的CancellationToken
实际上是最新的
为什么任务
不可能读取令牌的缓存值
注意:我问这个问题的动机是想知道我是否需要将我的
CancellationToken
实例变量设置为volatile
这是在CancellationTokenSource
内部处理的。用于跟踪CTS状态的私有变量已标记,这可防止内部状态检查过时
我问这个问题的动机是想知道我是否需要我的CancellationToken实例变量是可变的
您不需要这样做,因为检查是在内部处理的,并且已经为您正确地处理了
基本上,当您从
CancellationTokenSource
创建CancellationToken
时,该令牌包含对原始源的引用。此引用永远不会更改,因此通过调用ThrowIfCancellationRequested
在内部检查源的状态。由于源状态本身是易变的,所以它永远不会是“过时”数据。另外,CancellationTokenSource是一种引用类型。对CancellationTokenSource变量使用volatile只会使更改/读取对该字段的引用变得不稳定——这在TPL对CancellationTokenSource对象执行任何操作时不会发生。Rest assure,CancellationTokenSource内部是线程安全的,正如Reed所描述的那样。@PeterRitchie我想OP想知道他是否需要将他的CancellationToken
(结构)声明为volatile,而不是CTS。。。但是,是的,由于令牌是不可变的,并且持有对CTS的引用,它“只起作用”嗯,我一定是被“volatile”搞糊涂了,因为volatile
不能在结构上使用,因此CancellationToken
字段永远不能用“volatile”修饰。即使CancellationToken
不是不可变的,对值类型的任何更改也只能在该副本上看到——尽管在发布的代码中永远不应该制作ct
的副本。@PeterRitchie是的-我相信这是OP的一部分的误解-它不会起作用,但这是问题中提出的问题