Estou brincando com essas tarefas do Windows 8 WinRT e estou tentando cancelar uma tarefa usando o método abaixo e funciona até certo ponto. O método CancelNotification é chamado, o que faz você pensar que a tarefa foi cancelada, mas, em segundo plano, a tarefa continua sendo executada; depois de concluída, o status da tarefa é sempre concluído e nunca é cancelado. Existe uma maneira de interromper completamente a tarefa quando ela é cancelada?
private async void TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(CancelNotification);
source.CancelAfter(TimeSpan.FromSeconds(1));
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);
await task;
if (task.IsCompleted)
{
MessageDialog md = new MessageDialog(task.Result.ToString());
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("Uncompleted");
await md.ShowAsync();
}
}
private int slowFunc(int a, int b)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
}
return a + b;
}
private void CancelNotification()
{
}
c#
task-parallel-library
.net-4.5
Carlo
fonte
fonte
Respostas:
Leia-se sobre cancelamento (que foi introduzido no .NET 4.0 e é em grande parte inalterado desde então) eo padrão assíncrono baseado em tarefas , que fornece orientações sobre como usar
CancellationToken
comasync
métodos.Para resumir, você passa um
CancellationToken
para cada método que suporta cancelamento, e esse método deve verificá-lo periodicamente.fonte
CancellationToken
possui todos os ganchos necessários para interoperar com sistemas de cancelamento personalizados, mas nada pode cancelar um método não cancelável.Wait
ouResult
emasync
métodos; você sempre deve usarawait
, que desembrulha a exceção corretamente.CancellationToken.IsCancellationRequested
e sugere sugestões de exceções?Ou, para evitar modificações
slowFunc
(digamos que você não tenha acesso ao código fonte, por exemplo):Você também pode usar bons métodos de extensão em https://github.com/StephenCleary/AsyncEx e parecer simples como:
fonte
ConfigureAwait
caso contrário, você poderá se machucar nos aplicativos de interface do usuário.using
.Um caso que não foi coberto é como lidar com o cancelamento dentro de um método assíncrono. Tomemos, por exemplo, um caso simples em que você precise enviar alguns dados para um serviço, obtê-lo para calcular algo e retornar alguns resultados.
Se você deseja dar suporte ao cancelamento, a maneira mais fácil seria passar um token e verificar se ele foi cancelado entre cada chamada de método assíncrona (ou usando ContinueWith). Se as chamadas forem muito longas, você poderá esperar um pouco para cancelar. Eu criei um pequeno método auxiliar para falhar assim que cancelado.
Então, para usá-lo, basta adicionar
.WaitOrCancel(token)
a qualquer chamada assíncrona:Observe que isso não interromperá a tarefa que você estava esperando e continuará sendo executada. Você precisará usar um mecanismo diferente para interrompê-lo, como a
CancelAsync
chamada no exemplo, ou, melhor ainda, passar o mesmoCancellationToken
paraTask
que ele possa lidar com o cancelamento eventualmente. Não é recomendável tentar abortar o thread .fonte
UploadDataAsync
pode continuar em segundo plano, mas, uma vez concluída, não fará a ligaçãoCalculateAsync
porque essa parte já parou de esperar). Isso pode ou não ser problemático para você, especialmente se você deseja repetir a operação. PassarCancellationToken
todo o caminho é a opção preferida, quando possível.Eu só quero adicionar à resposta já aceita. Eu estava preso nisso, mas estava seguindo um caminho diferente ao lidar com o evento completo. Em vez de aguardar, adiciono um manipulador completo à tarefa.
Onde o manipulador de eventos se parece com isso
Com essa rota, todo o tratamento já está feito para você, quando a tarefa é cancelada, apenas aciona o manipulador de eventos e você pode ver se foi cancelado lá.
fonte