Compartilhar via


Barreira (.NET Framework)

A barreira é um user defined primitivo de sincronização que permite que vários threads (conhecido como participantes) para trabalhar simultaneamente em um algoritmo em fases. Cada participante executa até alcançar o ponto de barreira no código. A barreira representa o fim de uma fase do trabalho. Quando um participante alcança a barreira, ele bloqueia até que todos os participantes chegaram a barreira da mesma. Depois que todos os participantes tiverem chegado a barreira, opcionalmente, você pode chamar a uma ação de post-phase. Este post-phase ação pode ser usada para executar ações por um único thread enquanto todos os outros threads ainda são bloqueados. Depois que a ação foi executada, os participantes são todos desbloqueados.

O trecho de código a seguir mostra um padrão de barreira básica.


' 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

 // 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();

 }

Para obter um exemplo completo, consulte Como: Sincronizar as operações simultâneas com uma barreira.

Adicionando e removendo os participantes

Quando você cria um Barrier, especifique o número de participantes. Você também pode adicionar ou remover participantes dinamicamente a qualquer momento. Por exemplo, se um participante resolver sua parte do problema, você pode armazenar o resultado, a execução de parada em que o thread e, em seguida, chame RemoveParticipant a diminuir o número de participantes na barreira. Quando você adiciona um participante chamando AddParticipant, o valor de retorno Especifica o número da fase atual, que pode ser útil para inicializar o trabalho do novo participante.

Barreiras quebradas

Os deadlocks podem ocorrer se um participante falhar alcançar a barreira. Para evitar esses bloqueios, use os métodos sobrecarregados da SignalAndWait método para especificar um período de tempo limite e um símbolo de cancelamento. Essas sobrecargas retornar um valor booleano que cada participante pode verificar antes que ele continua para a próxima fase.

Exceções de post-Phase

Se o delegado post-phase lança uma exceção, ele é encapsulado em um BarrierPostPhaseException objeto que será propagado para todos os participantes.

Barreira Versus ContinueWhenAll

As barreiras são especialmente úteis quando os threads estiver executando várias fases em loops. Se o seu código requer apenas uma ou duas fases, considere a possibilidade de usar System.Threading.Tasks.Task objetos com qualquer tipo de associação implícita, incluindo:

Para obter mais informações, consulte Como: A cadeia de várias tarefas com continuação.

Consulte também

Tarefas

Como: Sincronizar as operações simultâneas com uma barreira

Outros recursos

Threading objetos e recursos