Un permite la cancelación cooperativa entre subprocesos, elementos de trabajo del grupo de subprocesos u objetos . En este artículo, me gustaría discutir el mecanismo que se aplica a los objetos Task. CancellationToken Task Cuando ejecuta una tarea en C#, puede llevar un tiempo ejecutarla. En algunos casos, le gustaría cancelar una operación tan larga. Puede haber varias razones: tiempo de espera de la operación, exceder los límites de recursos, etc. el algoritmo Cree un objeto del tipo que indique la cancelación del token. CancellationTokenSource Pase la propiedad como un objeto token a la tarea. CancellationTokenSource.Token Defina el comportamiento de la tarea para terminar la operación de acuerdo con la señal de cancelación. Llame al método que establece la propiedad en un valor . Eso significa que el método no cancela la operación en sí. Simplemente cambia el valor de la propiedad . Nosotros, como desarrolladores, tenemos que definir la lógica de cancelación por nosotros mismos. CancellationTokenSource.Cancel() CancellationToken.IsCancellationRequested true Cancel() IsCancellationRequested El tipo implementa la interfaz y debe liberarse cuando se completa una tarea. Se puede hacer manualmente llamando al método o vi la construcción. CancellationTokenSource IDisposable Dispose() using Ejemplo de código para demostrar el algoritmo anterior: // initialize cancellation objects CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); CancellationToken token = cancelTokenSource.Token; // execute a parallel operation Task task = new Task(() => { some_operations }, token); task.Start(); // cancel the operation cancelTokenSource.Cancel(); // release resources cancelTokenSource.Dispose(); Discutamos el en detalle. Hay dos formas de definir la lógica de finalización de la tarea mediante un token de cancelación: paso #3 Utilice el operador de para salir de la ejecución de la tarea. En este caso, el estado de la tarea será . return TaskStatus.RunToCompletion Ejecute la excepción de tipo a través de la llamada al método . En este caso, el estado de la tarea será . OperationCanceledException ThrowIfCancellationRequested() TaskStatus.Canceled Tarea completa a través del operador de return public static void Main(string[] args) { CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); CancellationToken token = cancelTokenSource.Token; Task task = new Task(() => { for (int i = 1; i < 100; i++) { if (token.IsCancellationRequested) { Console.WriteLine("Operation is canceled"); return; } Console.WriteLine($"Count is equal to '{i}'"); //add some timeout to emulate real-life execution Thread.Sleep(10); } }, token); task.Start(); // add some timeout to emulate real-life execution Thread.Sleep(100); // cancel the parallel operation cancelTokenSource.Cancel(); // wait till the operation is completed task.Wait(); // check the operation status Console.WriteLine($"Task Status is equal to '{ task.Status }'"); // release resources cancelTokenSource.Dispose(); } El resultado de esta ejecución es el siguiente: Count is equal to '1' Count is equal to '2' Count is equal to '3' Count is equal to '4' Count is equal to '5' Operation is canceled Task Status is equal to 'RanToCompletion' Tarea completa a través de la llamada al método ThrowIfCancellationRequested() public static void Main(string[] args) { CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); CancellationToken token = cancelTokenSource.Token; Task task = new Task(() => { for (int i = 1; i < 100; i++) { if (token.IsCancellationRequested) token.ThrowIfCancellationRequested(); Console.WriteLine($"Count is equal to '{i}'"); //add some timeout to emulate real-life execution Thread.Sleep(10); } }, token); try { task.Start(); // add some timeout to emulate real-life execution Thread.Sleep(100); // cancel the parallel operation cancelTokenSource.Cancel(); // wait till the operation is completed task.Wait(); } catch (AggregateException ae) { foreach (Exception e in ae.InnerExceptions) { if (e is TaskCanceledException) Console.WriteLine("Operation is canceled"); else Console.WriteLine(e.Message); } } finally { // release resources cancelTokenSource.Dispose(); } // check the operation status Console.WriteLine($"Task Status is equal to '{ task.Status }'"); } El resultado de esta ejecución es el siguiente: Count is equal to '1' Count is equal to '2' Count is equal to '3' Count is equal to '4' Count is equal to '5' Operation is canceled Task Status is equal to 'Canceled' La excepción lanzada aparecerá como una de . Si la tarea se canceló a través de la llamada al método , la excepción será del tipo . El código verifica este tipo para un manejo adecuado; de lo contrario, maneje otro motivo de excepción. InnerException AggregateException ThrowIfCancellationRequested() TaskCanceledException La excepción se lanzará solo en caso de que se llame al método o para la tarea. De lo contrario, no se lanza ninguna excepción, solo se establece . Wait() WaitAll() TaskStatus.Canceled Controlador de cancelación de operaciones de registro Otra forma de definir la lógica de la cancelación de la tarea es usar el método . Registra un delegado de que se llamará cuando se cancele . Register() acción CancellationToken public static void Main(string[] args) { CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); CancellationToken token = cancelTokenSource.Token; Task task = new Task(() => { int i = 1; token.Register(() => { Console.WriteLine("Operation is canceled"); i = 100; Console.WriteLine($"Count is equal to '{i}'"); }); for (; i < 100; i++) { Console.WriteLine($"Count is equal to '{i}'"); //add some timeout to emulate real-life execution Thread.Sleep(10); } }, token); task.Start(); // add some timeout to emulate real-life execution Thread.Sleep(100); // cancel the parallel operation cancelTokenSource.Cancel(); // wait till the operation is completed task.Wait(); // check the operation status Console.WriteLine($"Task Status is equal to '{ task.Status }'"); // release resources cancelTokenSource.Dispose(); } El resultado de esta ejecución es el siguiente: Count is equal to '1' Count is equal to '2' Count is equal to '3' Count is equal to '4' Count is equal to '5' Operation is canceled Count is equal to '100' Task Status is equal to 'RanToCompletion' En este código, el método se llama y se activa el delegado definido en el método . En este ejemplo, el código establece la variable en el valor , lo que provoca el final de la ejecución de la tarea. cancelTokenSource.Cancel() token.Register() i 100 Si el código no espera la competencia de la operación, el estado de la tarea será . Si se llama al método o , el estado de la tarea será . TaskStatus.Running Wait() WaitAll() TaskStatus.RanToCompletion Resumen: uso de un token de cancelación La cancelación de la tarea es muy importante para optimizar la lógica de su aplicación. Es posible que deba cancelar la tarea por muchas razones: tiempo de espera de la operación, exceso de los límites de recursos, etc. Siempre debe manejar la lógica de cancelación usted mismo. Puede hacerlo mediante el operador de o mediante la llamada al método . return ThrowIfCancellationRequested()