Mam kod, który tworzy token anulowania
public partial class CardsTabViewModel : BaseViewModel
{
public CancellationTokenSource cts;
public async Task OnAppearing()
{
cts = new CancellationTokenSource(); // << runs as part of OnAppearing()
Kod, który go używa:
await GetCards(cts.Token);
public async Task GetCards(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
App.viewablePhrases = App.DB.GetViewablePhrases(Settings.Mode, Settings.Pts);
await CheckAvailability();
}
}
i kod, który później anuluje ten Token Anulowania, jeśli użytkownik odejdzie od ekranu, na którym działa powyższy kod:
public void OnDisappearing()
{
cts.Cancel();
Jeśli chodzi o anulowanie, czy jest to właściwy sposób anulowania tokena, gdy jest on używany w zadaniu?
W szczególności sprawdziłem to pytanie:
Użycie właściwości IsCancellationRequested?
i sprawia, że myślę, że nie robię anulowania we właściwy sposób, a może w sposób, który może powodować wyjątek.
Również w tym przypadku po anulowaniu powinienem zrobić cts.Dispose ()?
c#
xamarin
xamarin.forms
Alan2
źródło
źródło
Odpowiedzi:
CancellationTokenSource.Cancel()
jest prawidłowym sposobem na rozpoczęcie anulowania.Sondowanie
ct.IsCancellationRequested
pozwala uniknąć rzucaniaOperationCanceledException
. Ponieważ jego odpytywanie wymaga wykonania iteracji pętli, aby mogła odpowiedzieć na żądanie anulowania.Jeśli
GetViewablePhrases()
iCheckAvailability()
można je zmodyfikować, aby zaakceptowaćCancellationToken
, może to przyspieszyć anulowanie, kosztemOperationCanceledException
rzucenia.„powinienem robić cts.Dispose ()?” nie jest takie proste ...
Jest bardziej wytyczną niż zasadą.
Task
sam jest jednorazowy, ale prawie nigdy nie jest umieszczony bezpośrednio w kodzie.Zdarzają się przypadki (gdy
WaitHandle
używane są procedury obsługi wywołania zwrotnego lub anulowania), w których usunięciects
uwolni zasób / usunie katalog główny GC, który w innym przypadku zostałby uwolniony tylko przez Finalizator. Nie dotyczą one obecnego kodu, ale mogą w przyszłości.Dodanie wywołania
Dispose
po anulowaniu zagwarantuje, że zasoby te zostaną niezwłocznie zwolnione w przyszłych wersjach kodu.Musisz jednak poczekać na zakończenie działania kodu
cts
przed wywołaniem funkcji dispose lub zmodyfikować kod, aby poradził sobie zObjectDisposedException
użyciemcts
(lub jego tokena) po usunięciu.źródło
CancellationToken
parametr), możesz się pozbyć,WaitHandle
gdy inny wątek aktywnie na niego czeka :(Dispose
zOnDisappearing
.Cancel
...Cancel
to wewnętrzny zegar (jeśli jest używany).Ogólnie widzę uczciwe użycie Anuluj token w twoim kodzie, ale zgodnie ze Wzorem Asynchronicznym Zadania twój kod może nie zostać natychmiast anulowany.
Aby odpowiedzieć od razu, kod blokujący również powinien zostać anulowany
Od Ciebie należy usunąć, jeśli w przerwanym kodzie zarezerwowano wiele zasobów pamięci, powinieneś to zrobić.
źródło
Polecam zajrzeć na jedną z klas .net, aby w pełni zrozumieć, jak obsługiwać metody oczekiwania za pomocą CanncelationToken, wybrałem SeamaphoreSlim.cs
Możesz również wyświetlić całą klasę tutaj, https://referencesource.microsoft.com/#mscorlib/system/threading/SemaphoreSlim.cs,6095d9030263f169
źródło