Eu tenho um código que cria um token de cancelamento
public partial class CardsTabViewModel : BaseViewModel
{
public CancellationTokenSource cts;
public async Task OnAppearing()
{
cts = new CancellationTokenSource(); // << runs as part of OnAppearing()
Código que o utiliza:
await GetCards(cts.Token);
public async Task GetCards(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
App.viewablePhrases = App.DB.GetViewablePhrases(Settings.Mode, Settings.Pts);
await CheckAvailability();
}
}
e código que mais tarde cancela esse token de cancelamento se o usuário se afastar da tela em que o código acima está sendo executado:
public void OnDisappearing()
{
cts.Cancel();
Em relação ao cancelamento, esta é a maneira correta de cancelar o token quando ele está sendo usado em uma tarefa?
Em particular, verifiquei esta pergunta:
Uso da propriedade IsCancellationRequested?
e está me fazendo pensar que não estou cancelando da maneira correta ou talvez de uma maneira que possa causar uma exceção.
Além disso, nesse caso, depois que cancelei, devo fazer um cts.Dispose ()?
c#
xamarin
xamarin.forms
Alan2
fonte
fonte
Respostas:
CancellationTokenSource.Cancel()
é uma maneira válida de iniciar o cancelamento.A votação
ct.IsCancellationRequested
evita jogarOperationCanceledException
. Devido à sua pesquisa, é necessário que uma iteração do loop seja concluída antes de responder à solicitação de cancelamento.Se
GetViewablePhrases()
eCheckAvailability()
puder ser modificado para aceitar aCancellationToken
, isso poderá acelerar a resposta do cancelamento, ao custo de ter sidoOperationCanceledException
lançado."eu deveria estar fazendo um cts.Dispose ()?" não é tão simples ...
É mais uma diretriz do que uma regra.
Task
ele próprio é descartável, mas quase nunca é descartado diretamente no código.Existem casos (quando
WaitHandle
ou manipuladores de retorno de chamada de cancelamento são usados) em que o descarte liberariacts
um recurso / removeria uma raiz de GC que, de outra forma, seria liberada apenas por um Finalizador. Eles não se aplicam ao seu código como está, mas podem ser no futuro.A adição de uma chamada
Dispose
após o cancelamento garantiria que esses recursos fossem liberados imediatamente em versões futuras do código.No entanto, é necessário aguardar o código que
cts
termina antes de chamar o descarte ou modificar o código para lidar com oObjectDisposedException
uso dects
(ou seu token) após o descarte.fonte
CancellationToken
parâmetro), você poderá descartarWaitHandle
enquanto outro thread o aguarda ativamente :(Dispose
deOnDisappearing
.Cancel
...Cancel
é o temporizador interno (se usado).Em geral, vejo um uso justo do token de cancelamento no seu código, mas, de acordo com o padrão de tarefas assíncronas, seu código não pode ser cancelado imediatamente.
Para responder imediatamente, o código de bloqueio também deve ser cancelado
Depende de você se você deve Dispose, se houver muitos recursos de memória reservados no código interrompido, você deve fazê-lo.
fonte
Eu recomendo que você dê uma olhada em uma das classes .net para entender completamente como lidar com métodos de espera com CanncelationToken, peguei SeamaphoreSlim.cs
Você também pode visualizar toda a classe aqui, https://referencesource.microsoft.com/#mscorlib/system/threading/SemaphoreSlim.cs,6095d9030263f169
fonte