Exportar (0) Imprimir
Expandir todo
Este artículo se tradujo de forma manual. Mueva el puntero sobre las frases del artículo para ver el texto original. Más información.
Traducción
Original

CountdownEvent

System.Threading.CountdownEvent es una primitiva de sincronización que desbloquea los subprocesos en espera después de haber sido señalada cierto número de veces. CountdownEvent se ha diseñado para escenarios en los que, de lo contrario, habría que utilizar ManualResetEvent o ManualResetEventSlim y disminuir manualmente una variable antes de señalar el evento. Por ejemplo, en un escenario de bifurcación/combinación, puede crear un CountdownEvent que tiene un recuento señalado de 5 y, a continuación, iniciar cinco elementos de trabajo en el grupo de subprocesos y hacer que cada elemento de trabajo llame a Signal cuando se complete. Cada llamada a Signal disminuye el recuento señalado en 1. En el subproceso principal, la llamada a Wait se bloqueará hasta que el recuento señalado sea cero.

Nota Nota

Para el código que no tiene que interactuar con las API de sincronización de .NET Framework heredadas, considere el uso de objetos System.Threading.Tasks.Task o del método Invoke para un planteamiento aún más sencillo para expresar el paralelismo bifurcación/combinación.

CountdownEvent tiene estas características adicionales:

  • La operación de espera puede cancelarse con los token de cancelación.

  • Se puede incrementar su recuento señalado una vez creada la instancia.

  • Se pueden reutilizar las instancias después de que Wait haya vuelto mediante la llamada al método Reset.

  • Las instancias exponen un WaitHandle para la integración con otras API de sincronización de .NET Framework, como WaitAll.

En el ejemplo siguiente se muestra la forma de utilizar un CountdownEvent con elementos de trabajo ThreadPool.


IEnumerable<Data> source = GetData();
using (CountdownEvent e = new CountdownEvent(1))
{
    // fork work:
    foreach (Data element in source)
    {
        // Dynamically increment signal count.
        e.AddCount();
        ThreadPool.QueueUserWorkItem(delegate(object state)
         {
             try
             {
                 ProcessData(state);
             }
             finally
             {
                 e.Signal();
             }
         },
         element);
    }
    e.Signal();

    // The first element could be run on this thread.

    // Join with work.
    e.Wait();
}
// .,.


En el siguiente ejemplo se muestra cómo cancelar la operación de espera en CountdownEvent utilizando un token de cancelación. El modelo básico sigue el modelo de la cancelación unificada, que se presentó en .NET Framework 4. Para obtener más información, vea Cancelación en subprocesos administrados.


class CancelableCountdowEvent
{
    class Data
    {
        public int Num { get; set; }
        public Data(int i) { Num = i; }
        public Data() { }
    }

    class DataWithToken
    {
        public CancellationToken Token { get; set; }
        public Data Data { get; private set; }
        public DataWithToken(Data data, CancellationToken ct)
        {
            this.Data = data;
            this.Token = ct;
        }
    }
    static IEnumerable<Data> GetData()
    {
        return new List<Data>() { new Data(1), new Data(2), new Data(3), new Data(4), new Data(5) };
    }
    static void ProcessData(object obj)
    {
        DataWithToken dataWithToken = (DataWithToken)obj;
        if (dataWithToken.Token.IsCancellationRequested)
        {
            Console.WriteLine("Canceled before starting {0}", dataWithToken.Data.Num);
            return;
        }

        for (int i = 0; i < 10000; i++)
        {
            if (dataWithToken.Token.IsCancellationRequested)
            {
                Console.WriteLine("Cancelling while executing {0}", dataWithToken.Data.Num);
                return;
            }
            // Increase this value to slow down the program.
            Thread.SpinWait(100000);
        }
        Console.WriteLine("Processed {0}", dataWithToken.Data.Num);
    }

    static void Main(string[] args)
    {
        EventWithCancel();

        Console.WriteLine("Press enter to exit.");
        Console.ReadLine();
    }

    static void EventWithCancel()
    {
        IEnumerable<Data> source = GetData();
        CancellationTokenSource cts = new CancellationTokenSource();

        //Enable cancellation request from a simple UI thread.
        Task.Factory.StartNew(() =>
             {
                 if (Console.ReadKey().KeyChar == 'c')
                     cts.Cancel();
             });

        // Event must have a count of at least 1
        CountdownEvent e = new CountdownEvent(1);


        // fork work:
        foreach (Data element in source)
        {
            DataWithToken item = new DataWithToken(element, cts.Token);
            // Dynamically increment signal count.
            e.AddCount();
            ThreadPool.QueueUserWorkItem(delegate(object state)
             {
                 ProcessData(state);
                 if (!cts.Token.IsCancellationRequested)
                     e.Signal();
             },
             item);
        }
        // Decrement the signal count by the one we added
        // in the constructor.
        e.Signal();

        // The first element could be run on this thread.

        // Join with work or catch cancellation.
        try
        {
            e.Wait(cts.Token);
        }
        catch (OperationCanceledException oce)
        {
            if (oce.CancellationToken == cts.Token)
            {
                Console.WriteLine("User canceled.");
            }
            else throw; //We don't know who canceled us!
        }
        e.Dispose();

        //... 
    } //end method
} //end class


Observe que la operación de espera no cancela los subprocesos que la señalan. Normalmente, la cancelación se aplica a una operación lógica, lo que puede incluir esperar el evento y todos los elementos de trabajo que la espera esté sincronizando. En este ejemplo, a cada elemento de trabajo se pasa una copia del mismo token de cancelación para que pueda responder a la solicitud de cancelación.

Adiciones de comunidad

AGREGAR
Mostrar:
© 2014 Microsoft