По сравнению с предыдущим кодом для класса 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:\xxx\Token.cs:line 33
at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:\xxx\Token.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();
}
}
}
}
c#
multithreading
asynchronous
concurrency
synchronization
Полная защита
источник
источник
CancellationTokenSource
асинхронных методов, длительных методов с опросом и использования обратного вызова.Ответы:
Вы можете реализовать свой метод работы следующим образом:
Вот и все. Вам всегда нужно обрабатывать отмену самостоятельно - выходите из метода, когда подходит время для выхода (чтобы ваша работа и данные были в согласованном состоянии)
ОБНОВЛЕНИЕ: я предпочитаю не писать,
while (!cancelToken.IsCancellationRequested)
потому что часто есть несколько точек выхода, где вы можете безопасно прекратить выполнение по телу цикла, и цикл обычно имеет какое-то логическое условие для выхода (перебирать все элементы в коллекции и т. Д.). Поэтому я считаю, что лучше не смешивать эти условия, поскольку у них разные намерения.Предупреждение о том, как избегать
CancellationToken.ThrowIfCancellationRequested()
:Комментарий, о котором идет речь, от Иамона Нербона :
источник
@ BrainSlugs83
Вы не должны слепо доверять всему, что написано в stackoverflow. Комментарий в коде Йенса неверен, параметр не контролирует, генерируются исключения или нет.
MSDN очень ясно, что этот параметр контролирует, вы его читали? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx
Имя переменной также неверно, потому что Cancel вызывается
CancellationTokenSource
не для самого токена, а источник изменяет состояние каждого токена, которым он управляет.источник
Вы можете создать задачу с токеном отмены, когда вы приложение goto background, вы можете отменить этот токен.
Вы можете сделать это в PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle.
Другое решение - это пользовательский таймер в Xamarin.Forms, остановить таймер, когда приложение переходит в фоновый режим https://xamarinhelp.com/xamarin-forms-timer/
источник
Вы можете использовать
ThrowIfCancellationRequested
без обработки исключения!Использование
ThrowIfCancellationRequested
предназначено для использования изнутриTask
(а не aThread
). При использовании внутри aTask
вам не нужно самостоятельно обрабатывать исключение (и получать ошибку Unhandled Exception). Это приведет к выходу изTask
, иTask.IsCancelled
свойство будет True. Обработка исключений не требуется.В вашем конкретном случае, изменить
Thread
кTask
.источник
t.Start()
а нетTask.Run()
?Вы должны передать
CancellationToken
задачу Задаче, которая будет периодически отслеживать токен, чтобы узнать, запрашивается ли отмена.В этом случае операция завершится, когда будет запрошена отмена, и у
Task
объекта будетRanToCompletion
состояние. Если вы хотите, чтобы вас признали, что ваша задача была отменена , вы должны использоватьThrowIfCancellationRequested
для созданияOperationCanceledException
исключения.Надеюсь, это поможет лучше понять.
источник