Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何保证CancellationTokens是最新的?_C#_.net_Multithreading_Task Parallel Library_Cancellation Token - Fatal编程技术网

C# 如何保证CancellationTokens是最新的?

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.

微软在.NET4中使用了这一
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的一部分的误解-它不会起作用,但这是问题中提出的问题