CancellationTokens如何保证是最新的?

Eri*_*ric 5 .net c# multithreading task-parallel-library cancellation-token

微软给出了这个例子CancellationToken是.NET 4中使用.

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我的理解是,如果在一个线程上修改了一个变量,则由于缓存,另一个线程可能无法获得修改后的值.并且由于在CancellationToken主线程上被取消,线程如何Task确保CancellationToken它正在检查实际上是最新的?

为什么不能Task读取令牌的缓存值?

注意:我对此问题的动机来自于想知道我是否需要我的CancellationToken实例变量volatile.

Ree*_*sey 10

这是在内部处理的CancellationTokenSource.用于跟踪CTS状态的私有变量标记为volatile,这可防止内部状态检查失效.

我问这个的动机来自于想知道我是否需要我的CancellationToken实例变量是volatile.

您不需要这样做,因为检查是在内部处理的,并且已经为您正确处理.

基本上,当您创建一个CancellationTokenfrom时CancellationTokenSource,该标记包含对原始源的引用.此引用永远不会更改,因此调用ThrowIfCancellationRequested内部检查源的状态.由于源状态本身volatile,它永远不会"陈旧"数据.

  • 另外,CancellationTokenSource是一种引用类型.在CancellationTokenSource变量上使用volatile只会更改/读取对该字段volatile的引用 - 当TPL对CancellationTokenSource对象执行任何操作时,不会发生这种情况.Rest-assure,CancelingTokenSource内部是线程安全的,正如Reed所描述的那样. (2认同)