BarreiraBarrier

Um System.Threading.Barrier é um primitivo de sincronização definido pelo usuário que permite que vários threads (conhecidos como participantes) trabalhem simultaneamente em um algoritmo em fases.A System.Threading.Barrier is a synchronization primitive that enables multiple threads (known as participants) to work concurrently on an algorithm in phases. Cada participante executa até atingir o ponto de barreira no código.Each participant executes until it reaches the barrier point in the code. A barreira representa o final de uma fase de trabalho.The barrier represents the end of one phase of work. Quando um participante alcança a barreira, ela é bloqueada até que todos os participantes atinjam a mesma barreira.When a participant reaches the barrier, it blocks until all participants have reached the same barrier. Depois que todos os participantes tiverem chegado à barreira, opcionalmente, você poderá chamar uma ação pós-fase.After all participants have reached the barrier, you can optionally invoke a post-phase action. Esta ação pós-fase pode ser usada para executar ações por um único thread enquanto todos os outros threads ainda estiverem bloqueados.This post-phase action can be used to perform actions by a single thread while all other threads are still blocked. Após a ação ser executada, todos os participantes serão desbloqueados.After the action has been executed, the participants are all unblocked.

O snippet de código a seguir mostra um padrão de barreira básica.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 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 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 um exemplo completo, veja Como sincronizar operações simultâneas com uma barreira.For a complete example, see How to: synchronize concurrent operations with a Barrier.

Adicionar e remover participantesAdding and removing participants

Ao criar uma instância de Barrier, especifique o número de participantes.When you create a Barrier instance, specify the number of participants. Você também pode adicionar ou remover participantes dinamicamente a qualquer momento.You can also add or remove participants dynamically at any time. Por exemplo, se um participante resolver sua parte do problema, você poderá armazenar o resultado, parar a execução no thread e chamar Barrier.RemoveParticipant para diminuir o número de participantes na barreira.For example, if one participant solves its part of the problem, you can store the result, stop execution on that thread, and call Barrier.RemoveParticipant to decrement the number of participants in the barrier. Quando você adiciona um participante chamando Barrier.AddParticipant, o valor de retorno especifica o número de fase atual, que pode ser útil para inicializar o trabalho do novo participante.When you add a participant by calling Barrier.AddParticipant, the return value specifies the current phase number, which may be useful in order to initialize the work of the new participant.

Barreiras interrompidasBroken barriers

Os deadlocks podem ocorrer se um participante não conseguir alcançar a barreira.Deadlocks can occur if one participant fails to reach the barrier. Para evitar esses deadlocks, use as sobrecargas do método Barrier.SignalAndWait para especificar um período de tempo limite e um token de cancelamento.To avoid these deadlocks, use the overloads of the Barrier.SignalAndWait method to specify a time-out period and a cancellation token. Essas sobrecargas retorno um valor booliano que cada participante pode verificar antes de ele continuar para a próxima fase.These overloads return a Boolean value that every participant can check before it continues to the next phase.

Exceções pós-fasePost-phase exceptions

Se o representante da pós-fase lançar uma exceção, ele será encapsulado em um objeto BarrierPostPhaseException que será, em seguida, propagado para todos os participantes.If the post-phase delegate throws an exception, it is wrapped in a BarrierPostPhaseException object which is then propagated to all participants.

Barreira versus ContinueWhenAllBarrier versus ContinueWhenAll

As barreiras são especialmente úteis quando os threads estão executando várias fases em loops.Barriers are especially useful when the threads are performing multiple phases in loops. Caso seu código requeira somente uma ou duas fases de trabalho, considere o uso de objetos System.Threading.Tasks.Task com qualquer tipo de junção implícita, incluindo: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 obter mais informações, consulte Encadeando tarefas com tarefas de continuação.For more information, see Chaining Tasks by Using Continuation Tasks.

Confira tambémSee also