Created
July 23, 2015 23:44
-
-
Save Fhernd/14a69a2d39a7f67076f5 to your computer and use it in GitHub Desktop.
Demostración de uso de la clase CancellationTokenSource para la cancelación de operaciones asincrónicas.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// OrtizOL - xCSw - http://ortizol.blogspot.com | |
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace Receta.CSharp.R0304 | |
{ | |
public class Medicion | |
{ | |
public static void Main() | |
{ | |
Console.WriteLine(Environment.NewLine); | |
// Creación de objeto CancellationTokenSource: | |
CancellationTokenSource cts = new CancellationTokenSource(); | |
// Obtención de token de cancellación: | |
CancellationToken token = cts.Token; | |
// Generador de números aleatorios: | |
Random rnd = new Random(); | |
Object objLock = new Object(); | |
// Creación de lista de tareas: | |
List<Task<int[]>> tareas = new List<Task<int[]>>(); | |
// Creación de objeto TaskFactory con token de cancellación: | |
TaskFactory factory = new TaskFactory(token); | |
// Creación de cada una de las tareas: | |
for (int tarea = 0; tarea <= 10; ++tarea) | |
{ | |
int iteracion = tarea + 1; | |
// Agregación de tarea: | |
tareas.Add(factory.StartNew( () => { | |
int valor; | |
int[] mediciones = new int[10]; | |
for (int medicion = 1; medicion <= 10; ++medicion) | |
{ | |
lock (objLock) | |
{ | |
valor = rnd.Next(0, 101); | |
} | |
// Cancela el resto de mediciones cuando | |
// la medicion es igual 0: | |
if (valor == 0) | |
{ | |
// Emite señal de cancelación: | |
cts.Cancel(); | |
Console.WriteLine ("Cancelación de la tarea: {0}", iteracion); | |
break; | |
} | |
// Agrega la medición satisfactoria: | |
mediciones[medicion - 1] = valor; | |
} | |
return mediciones; | |
}, token)); | |
} | |
try | |
{ | |
// Se asegura que el promedio sea calculado una vez | |
// todas las mediciones hayan sido satisfactorias: | |
Task<double> resultadoPromedios = factory.ContinueWhenAll(tareas.ToArray(), | |
(resultados) => { | |
Console.WriteLine ("Calculando el promedio general..."); | |
int suma = 0; | |
int numMediciones = 0; | |
// Calculo del promedio por cada instrumento: | |
foreach(var instrumento in resultados) | |
{ | |
foreach(var medicion in instrumento.Result) | |
{ | |
suma += medicion; | |
++numMediciones; | |
} | |
} | |
return suma / (double) numMediciones; | |
}, token); | |
Console.WriteLine ("El promedio es igual: {0:00}", resultadoPromedios.Result); | |
} | |
catch(AggregateException ae) | |
{ | |
foreach(Exception e in ae.InnerExceptions) | |
{ | |
if (e is TaskCanceledException) | |
{ | |
Console.WriteLine ("No se pudo calcular el promedio."); | |
} | |
else | |
{ | |
Console.WriteLine ("Excepción: {0}", e.GetType().Name); | |
} | |
} | |
} | |
finally | |
{ | |
cts.Dispose(); | |
} | |
Console.WriteLine(Environment.NewLine); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment