Как гарантировать, что CancellationTokens будет обновляться?
Microsoft приводит этотпример использования 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();
}
}
Однако, мое понимание заключается в том, что если переменная изменяется в одном потоке, другой поток может не получить измененное значение из-за кэширования. И поскольку CancellationToken
отменяется в главном потоке, как поток Task
может быть уверен, что CancellationToken
, который он проверяет, действительно является актуальным?
Почему невозможно, чтобы Task
считывал кэшированное значение жетон?
Примечание: моя мотивация в вопросе об этом возникает из вопроса, нужно ли мне, чтобы мои переменные экземпляра CancellationToken
были volatile
.
1 ответ:
Это обрабатывается внутри
CancellationTokenSource
. Частная переменная, используемая для отслеживания состояния CTS, помечена как volatile, что предотвращает устаревание внутренней проверки состояния.Моя мотивация в вопросе об этом возникает из вопроса, нужно ли мне, чтобы переменные экземпляра CancellationToken были изменчивыми.
Вам не нужно этого делать, так как проверка выполняется внутренне и уже выполняется должным образом для вас.
В основном, когда вы создаете
CancellationToken
начиная сCancellationTokenSource
, маркер содержит ссылку на исходный источник. Эта ссылка никогда не может измениться, поэтому вызовThrowIfCancellationRequested
проверяет состояние источника внутренне. Поскольку исходное состояние само по себеvolatile
, оно никогда не бывает "устаревшим".