1
resposta

A notificação não funcionou! (2)

Testando o código de lançamento de exceção de acordo com a aula, eu não consegui capturar a exceção que deveria ocorrer. Acusava que não havia tratamento de exceção, no caso a OperationCanceledException.

static void Main(string[] args)
        {
            CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
            Console.WriteLine("Tecle algo para parar o relógio");
            Task contagem = new Task(() => ContagemRegressiva(cancelTokenSource.Token));
            contagem.Start();
            Console.ReadKey();
            if (contagem.IsCompleted)
            {
                Console.WriteLine("A contagem foi completada.");
            }
            else 
            { 
                try
                {
                    cancelTokenSource.Cancel();
                    contagem.Wait();
                }
                catch (OperationCanceledException ex) 
                {
                    Console.WriteLine("A contagem foi interrompida: " + ex.Message);
                } 
            }
            Console.ReadLine();
        }

        static void ContagemRegressiva(CancellationToken cancelToken)
        {
            int contador = 7;
            while (contador > -1 && !cancelToken.IsCancellationRequested)
            {
                Console.WriteLine("Contador: {0}", contador);
                Thread.Sleep(500);
                contador--;
            }
            cancelToken.ThrowIfCancellationRequested();
        }

Resolvi o problema, mas sem estar muito claro com o seguinte código. Segundo a documentação da Microsoft:

Wait(CancellationToken)

Waits for the Task to complete execution. The wait terminates if a cancellation token is canceled before the task completes.

static void Main(string[] args)
        {
            CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
            Console.WriteLine("Tecle algo para parar o relógio");
            Task contagem = new Task(() => ContagemRegressiva(cancelTokenSource.Token));
            contagem.Start();
            Console.ReadKey();
            if (contagem.IsCompleted)
            {
                Console.WriteLine("A contagem foi completada.");
            }
            else 
            { 
                try
                {
                    cancelTokenSource.Cancel();
                    //Uando a sobrecarga do método Task.Wait passando como parâmetro o CancelationToken
                    contagem.Wait(cancelTokenSource.Token);
                }
                catch (OperationCanceledException ex) 
                {
                    Console.WriteLine("A contagem foi interrompida: " + ex.Message);
                } 
            }
            Console.ReadLine();
        }

        static void ContagemRegressiva(CancellationToken cancelToken)
        {
            int contador = 7;
            while (contador > -1 && !cancelToken.IsCancellationRequested)
            {
                Console.WriteLine("Contador: {0}", contador);
                Thread.Sleep(500);
                contador--;
            }
            //Removido o lançamento da exceção
            //cancelToken.ThrowIfCancellationRequested();
        }

Se alguém puder explicar, não entendi nem sei se o que fiz está fazendo o uso correto da sobrecarga do Wait().

1 resposta

Olá, Leonardo! Tudo certo com você?

Peço desculpas pela demora no retorno a sua mensagem.

No código original, você utilizou o método contagem.Wait() para aguardar a conclusão da tarefa, mas não passou nenhum parâmetro. Na nova versão do código, você utilizou a sobrecarga do método Wait() que recebe um CancellationToken como parâmetro: contagem.Wait(cancelTokenSource.Token).

Essa sobrecarga do método Wait() permite que você especifique um CancellationToken para que a espera seja interrompida caso esse token, seja cancelado. Ou seja, se o token for cancelado antes da conclusão da tarefa, a espera será finalizada e uma OperationCanceledException será lançada.

No seu caso, você está passando o cancelTokenSource.Token como parâmetro para o método Wait(), ou seja, você está informando que a espera deve ser interrompida caso o token seja cancelado. Isso garante que, ao chamar cancelTokenSource.Cancel(), a espera será finalizada e a exceção será capturada no bloco catch.

Portanto, o uso da sobrecarga do método Wait() com o CancellationToken está correto e vai permitir que você capture a exceção OperationCanceledException quando o token for cancelado.

Todavia, vale ressaltar que como você postou sua pergunta há algum tempo é possível que a constante evolução da tecnologia impacte na resolução da sua dúvida.

Sendo assim, caso queira se aprofundar neste tema e com conteúdos atualizados, recomendo os materiais abaixo:

Espero ter ajudado e bons estudos!