Barrier (.NET Framework)Barrier (.NET Framework)

Una barrera es un primitivo de sincronización definido por el usuario que permite que varios subprocesos (conocidos como participantes) trabajen simultáneamente en un algoritmo por fases.A barrier is a user-defined synchronization primitive that enables multiple threads (known as participants) to work concurrently on an algorithm in phases. Cada participante se ejecuta hasta que alcanza el punto de barrera en el código.Each participant executes until it reaches the barrier point in the code. La barrera representa el final de una fase de trabajo.The barrier represents the end of one phase of work. Cuando un participante alcanza la barrera, se bloquea hasta que todos los participantes alcancen la misma barrera.When a participant reaches the barrier, it blocks until all participants have reached the same barrier. Cuando todos los participantes alcanzan la barrera, opcionalmente puede invocar una acción posterior a la fase.After all participants have reached the barrier, you can optionally invoke a post-phase action. Esta acción posterior a la fase puede usarse para realizar acciones con un solo subproceso mientras todos los demás subprocesos siguen bloqueados.This post-phase action can be used to perform actions by a single thread while all other threads are still blocked. Una vez ejecutada la acción, se desbloquean todos los participantes.After the action has been executed, the participants are all unblocked.

El fragmento de código siguiente muestra un modelo de barrera básico.The following code snippet shows a basic barrier pattern.


 // Create the Barrier object, and supply a post-phase delegate 
 // to be invoked at the end of each phase.
 Barrier barrier = new Barrier(2, (bar) => 
     {
         // Examine results from all threads, determine 
         // whether to continue, create inputs for next phase, etc. 
         if (someCondition)
             success = true;
     });       
 
     
 // Define the work that each thread will perform. (Threads do not
 // have to all execute the same method.)
 void CrunchNumbers(int partitionNum)
 {
     // Up to System.Int64.MaxValue phases are supported. We assume
     // in this code that the problem will be solved before that.
     while (success == false)
     {
         // Begin phase:
         // Process data here on each thread, and optionally
         // store results, for example:
         results[partitionNum] = ProcessData(data[partitionNum]);

         // End phase:
         // After all threads arrive,post-phase delegate
         // is invoked, then threads are unblocked. Overloads
         // accept a timeout value and/or CancellationToken.
         barrier.SignalAndWait();
     }
 }

 // Perform n tasks to run in in parallel. For simplicity
// all threads execute the same method in this example.
 static void Main()
 {
     var app = new BarrierDemo();
     Thread t1 = new Thread(() => app.CrunchNumbers(0));
     Thread t2 = new Thread(() => app.CrunchNumbers(1));
     t1.Start();
     t2.Start();
     
 }

' Create the Barrier object, and supply a post-phase delegate 
' to be invoked at the end of each phase.
Dim barrier = New Barrier(2, Sub(bar)
                                 ' Examine results from all threads, determine 
                                 ' whether to continue, create inputs for next phase, etc. 
                                 If (someCondition) Then
                                     success = True
                                 End If
                             End Sub)



' Define the work that each thread will perform. (Threads do not
' have to all execute the same method.)
Sub CrunchNumbers(ByVal partitionNum As Integer)

    ' Up to System.Int64.MaxValue phases are supported. We assume
    ' in this code that the problem will be solved before that.
    While (success = False)

        ' Begin phase:
        ' Process data here on each thread, and optionally
        ' store results, for example:
        results(partitionNum) = ProcessData(myData(partitionNum))

        ' End phase:
        ' After all threads arrive,post-phase delegate
        ' is invoked, then threads are unblocked. Overloads
        ' accept a timeout value and/or CancellationToken.
        barrier.SignalAndWait()
    End While
End Sub

' Perform n tasks to run in in parallel. For simplicity
' all threads execute the same method in this example.
Shared Sub Main()

    Dim app = New BarrierDemo()
    Dim t1 = New Thread(Sub() app.CrunchNumbers(0))
    Dim t2 = New Thread(Sub() app.CrunchNumbers(1))
    t1.Start()
    t2.Start()
End Sub

Para obtener un ejemplo completo, consulte Cómo: Sincronizar operaciones simultáneas con una barrera.For a complete example, see How to: Synchronize Concurrent Operations with a Barrier.

Agregar y quitar participantesAdding and Removing Participants

Cuando cree una Barrier, especifique el número de participantes.When you create a Barrier, specify the number of participants. También puede agregar o quitar participantes dinámicamente en cualquier momento.You can also add or remove participants dynamically at any time. Por ejemplo, si un participante resuelve su parte del problema, puede almacenar el resultado, detener la ejecución de ese subproceso y llamar a RemoveParticipant para reducir el número de participantes en la barrera.For example, if one participant solves its part of the problem, you can store the result, stop execution on that thread, and call RemoveParticipant to decrement the number of participants in the barrier. Cuando se agrega un participante mediante una llamada a AddParticipant, el valor devuelto especifica el número de fase actual, que puede ser útil para inicializar el trabajo del nuevo participante.When you add a participant by calling AddParticipant, the return value specifies the current phase number, which may be useful in order to initialize the work of the new participant.

Barreras rotasBroken Barriers

Si un participante no consigue alcanzar la barrera, pueden producirse interbloqueos.Deadlocks can occur if one participant fails to reach the barrier. Para evitar estos interbloqueos, use las sobrecargas del método SignalAndWait para especificar un período de tiempo de espera y un token de cancelación.To avoid these deadlocks, use the overloads of the SignalAndWait method to specify a time-out period and a cancellation token. Estas sobrecargas devuelven un valor booleano que cada participante puede comprobar antes de continuar con la fase siguiente.These overloads return a Boolean value that every participant can check before it continues to the next phase.

Excepciones posteriores a la fasePost-Phase Exceptions

Si el delegado posterior a la fase produce una excepción, se encapsula en un objeto BarrierPostPhaseException que después se propaga a todos los participantes.If the post-phase delegate throws an exception, it is wrapped in a BarrierPostPhaseException object which is then propagated to all participants.

Barrier frente a ContinueWhenAllBarrier Versus ContinueWhenAll

Las barreras resultan especialmente útiles cuando los subprocesos realizan varias fases en bucles.Barriers are especially useful when the threads are performing multiple phases in loops. Si el código solo requiere una o dos fases de trabajo, piense en usar objetos System.Threading.Tasks.Task con cualquier tipo de unión implícita, incluidas:If your code requires only one or two phases of work, consider whether to use System.Threading.Tasks.Task objects with any kind of implicit join, including:

Para más información, consulte Chaining Tasks by Using Continuation Tasks (Encadenar tareas mediante tareas de continuación).For more information, see Chaining Tasks by Using Continuation Tasks.

Vea tambiénSee Also

Objetos y características de subprocesosThreading Objects and Features
Sincronizar operaciones simultáneas con una clase BarrierHow to: Synchronize Concurrent Operations with a Barrier