W porównaniu z poprzednim kodem dla klasy RulyCanceler , chciałem uruchomić kod przy użyciu CancellationTokenSource
.
Jak go używać, jak wspomniano w tokenach anulowania , tj. Bez rzucania / łapania wyjątku? Czy mogę korzystać z IsCancellationRequested
nieruchomości?
Próbowałem tego użyć w ten sposób:
cancelToken.ThrowIfCancellationRequested();
i
try
{
new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
ale to spowodowało błąd cancelToken.ThrowIfCancellationRequested();
w czasie wykonywania w metodzie 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:
Kod, który pomyślnie uruchomiłem, przechwycił OperationCanceledException w nowym wątku:
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
W pełni odporny
źródło
źródło
CancellationTokenSource
z metodami asynchronicznymi, długotrwałych metod z odpytywaniem i używania wywołania zwrotnego.Odpowiedzi:
Możesz zaimplementować swoją metodę pracy w następujący sposób:
Otóż to. Zawsze musisz samodzielnie załatwić anulowanie - wyjdź z metody, gdy nadejdzie odpowiedni czas na wyjście (aby Twoja praca i dane były spójne)
AKTUALIZACJA: Wolę nie pisać,
while (!cancelToken.IsCancellationRequested)
ponieważ często jest kilka punktów wyjścia, w których można bezpiecznie zatrzymać wykonywanie w treści pętli, a pętla zwykle ma jakiś logiczny warunek do zakończenia (iteracja po wszystkich elementach w kolekcji itp.). Dlatego uważam, że lepiej nie mieszać tych warunków, ponieważ mają one różne intencje.Ostrzeżenie dotyczące unikania
CancellationToken.ThrowIfCancellationRequested()
:Komentarz w pytaniu przez Eamon Nerbonne :
źródło
@ BrainSlugs83
Nie powinieneś ślepo ufać wszystkiemu, co zostało opublikowane w stackoverflow. Komentarz w kodzie Jensa jest niepoprawny, parametr nie kontroluje, czy wyjątki są generowane, czy nie.
MSDN jasno określa, co kontroluje ten parametr, czytałeś? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx
Nazwa zmiennej jest również nieprawidłowa, ponieważ Cancel jest wywoływana na
CancellationTokenSource
samym tokenie, a nie na samym tokenie, a źródło zmienia stan każdego tokenu, którym zarządza.źródło
Możesz utworzyć zadanie z tokenem anulowania, kiedy aplikacja przejdzie do tła, możesz anulować ten token.
Możesz to zrobić w PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle
Rozwiązanie Anther to licznik czasu użytkownika w Xamarin.Forms, zatrzymaj licznik czasu, gdy aplikacja przejdzie w tło https://xamarinhelp.com/xamarin-forms-timer/
źródło
Państwo może używać
ThrowIfCancellationRequested
bez obsługi wyjątku!Użycie z
ThrowIfCancellationRequested
ma być używane od wewnątrz aTask
(nie aThread
). Gdy jest używany w ramachTask
, nie musisz samodzielnie obsługiwać wyjątku (i otrzymywać błędu nieobsługiwanego wyjątku). Spowoduje to opuszczenieTask
, aTask.IsCancelled
właściwość będzie miała wartość True. Nie jest wymagana obsługa wyjątków.W twoim przypadku szczególnego, zmień
Thread
DoTask
.źródło
t.Start()
a nieTask.Run()
?Musisz przekazać
CancellationToken
zadanie do zadania, które będzie okresowo monitorować token, aby sprawdzić, czy żądane jest anulowanie.W takim przypadku operacja zakończy się, gdy zażąda się anulowania, a
Task
będzie miałRanToCompletion
stan. Jeśli chcesz otrzymać potwierdzenie, że Twoje zadanie zostało anulowane , musisz użyć,ThrowIfCancellationRequested
aby zgłosićOperationCanceledException
wyjątek.Mam nadzieję, że to pomoże lepiej zrozumieć.
źródło