6

Microsoft在 .NET 4 中给出了这个使用示例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它正在检查实际上是最新的?

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

注意:我提出这个问题的动机是想知道我是否需要CancellationToken将实例变量设置为volatile.

4

1 回答 1

11

这是在内部处理的CancellationTokenSource。用于跟踪 CTS 状态的私有变量被标记为volatile,这可以防止内部状态检查过时。

我提出这个问题的动机是想知道我是否需要我的 CancellationToken 实例变量是可变的。

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

基本上,当您从 中创建 a 时CancellationTokenCancellationTokenSource令牌包含对原始源的引用。这个引用永远不会改变,所以调用ThrowIfCancellationRequested内部检查源的状态。由于源状态是它本身volatile,它永远不是“陈旧”的数据。

于 2012-08-07T16:28:47.897 回答