6

Microsoftは、この.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

Taskがトークンのキャッシュされた値を読み取ることができないのはなぜですか?

注:CancellationTokenこれを尋ねる動機は、インスタンス変数がである必要があるかどうか疑問に思うことから生じますvolatile

4

1 に答える 1

11

これは、内部で処理されますCancellationTokenSource。CTSの状態を追跡するために使用されるプライベート変数は、volatileとマークされており、内部状態チェックが古くなるのを防ぎます。

これを尋ねる動機は、CancellationTokenインスタンス変数を揮発性にする必要があるかどうか疑問に思うことから生じます。

チェックは内部で処理され、すでに適切に処理されているため、これを行う必要はありません。

基本的に、CancellationTokenからを作成するCancellationTokenSourceと、トークンには元のソースへの参照が含まれます。この参照は変更できないため、を呼び出してThrowIfCancellationRequestedソースの状態を内部的にチェックします。ソースの状態自体がvolatile「古い」データになることはありません。

于 2012-08-07T16:28:47.897 に答える