Как использовать свойство CancellationToken?


по сравнению с предыдущим кодом для класса RulyCanceler, Я хотел, чтобы запустить код с помощью CancellationTokenSource.

как я могу использовать его, как указано в Токены Отмены, т. е. без метания / ловли исключения? Могу ли я использовать IsCancellationRequested собственность?

Я попытался использовать его так:

cancelToken.ThrowIfCancellationRequested();

и

try
{
  new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
  Console.WriteLine("Canceled!");
}

но это дало ошибку времени выполнения на cancelToken.ThrowIfCancellationRequested(); методом Work(CancellationToken cancelToken):

System.OperationCanceledException was unhandled
  Message=The operation was canceled.
  Source=mscorlib
  StackTrace:
       at System.Threading.CancellationToken.ThrowIfCancellationRequested()
       at _7CancellationTokens.Token.Work(CancellationToken cancelToken) in C:xxxToken.cs:line 33
       at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:xxxToken.cs:line 22
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

код, который я успешно выполнил поймал OperationCanceledException в новом потоке:

using System;
using System.Threading;
namespace _7CancellationTokens
{
  internal class Token
  {
    private static void Main()
    {
      var cancelSource = new CancellationTokenSource();
      new Thread(() =>
      {
         try
         {
           Work(cancelSource.Token); //).Start();
         }
         catch (OperationCanceledException)
         {
            Console.WriteLine("Canceled!");
         }
         }).Start();

      Thread.Sleep(1000);
      cancelSource.Cancel(); // Safely cancel worker.
      Console.ReadLine();
    }
    private static void Work(CancellationToken cancelToken)
    {
      while (true)
      {
        Console.Write("345");
        cancelToken.ThrowIfCancellationRequested();
      }
    }
  }
}
4 81

4 ответа:

вы можете реализовать свой метод работы следующим образом:

private static void Work(CancellationToken cancelToken)
{
    while (true)
    {
        if(cancelToken.IsCancellationRequested)
        {
            return;
        }
        Console.Write("345");
    }
}

вот именно. Вы всегда должны обрабатывать отмену самостоятельно-выход из метода, когда это подходящее время для выхода (так что ваша работа и данные находятся в согласованном состоянии)

обновление: Я предпочитаю не писать!--1--> потому что часто есть несколько точек выхода, где вы можете остановить выполнение безопасно через тело цикла, и цикл обычно имеет некоторое логическое условие для выхода (итерация по всем элементам в коллекции и т. д.). Поэтому я считаю, что лучше не смешивать эти условия, поскольку они имеют разные намерения.

@BrainSlugs83

вы не должны слепо доверять всему, что опубликовано на stackoverflow. Комментарий в коде Jens неверен, параметр не контролирует, создаются ли исключения или нет.

MSDN очень ясно, что этот параметр контролирует, вы его читали? http://msdn.microsoft.com/en-us/library/dd321703 (v=vs. 110). aspx

Если throwOnFirstException имеет значение true, исключение будет немедленно распространение из вызова чтобы отменить, предотвращая оставшиеся обратные вызовы и отменяемые операции от обработки. Если throwOnFirstException является false, эта перегрузка будет агрегировать любые исключения, брошенные в AggregateException, такие что один обратный вызов создание исключения не будет препятствовать другим зарегистрированным обратным вызовам быть казненным.

имя переменной также неверно, потому что Cancel вызывается на CancellationTokenSource не сам токен и источник изменяет состояние каждого токен им управляет.

вы можете использовать ThrowIfCancellationRequested без обработки исключения!

использование ThrowIfCancellationRequested предназначено для использования из задание (не поток). При использовании в задаче вам не нужно обрабатывать исключение самостоятельно (и получать необработанную ошибку исключения). Это приведет к тому, что вы оставите задачу и задачу.Свойство IsCancelled будет истинным. Обработка исключений не требуется.

в вашем конкретном случае измените поток к заданию.

try
{
  var t = new Task(() => Work(cancelSource.Token));
  t.Start();
}
if (t.IsCancelled)
  Console.WriteLine("Canceled!");
}

вы можете создать задачу с токеном отмены, когда вы приложение goto background вы можете отменить этот токен.

вы можете сделать это в PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle

var cancelToken = new CancellationTokenSource();
Task.Factory.StartNew(async () => {
    await Task.Delay(10000);
    // call web API
}, cancelToken.Token);

//this stops the Task:
cancelToken.Cancel(false);

пыльник решение является таймер пользователя в Xamarin.Формы, остановить таймер, когда приложение Гото фон https://xamarinhelp.com/xamarin-forms-timer/