Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
A System.Threading.Barrier est une primitive de synchronisation qui permet à plusieurs threads (appelés participants) de fonctionner simultanément sur un algorithme en phases. Chaque participant s’exécute jusqu’à ce qu’il atteigne le point de barrière dans le code. La barrière représente la fin d’une phase de travail. Lorsqu’un participant atteint la barrière, il bloque jusqu’à ce que tous les participants aient atteint la même barrière. Une fois que tous les participants ont atteint la barrière, vous pouvez éventuellement appeler une action post-phase. Cette action post-phase peut être utilisée pour effectuer des actions par un thread unique, tandis que tous les autres threads sont toujours bloqués. Une fois l’action exécutée, les participants sont tous débloqués.
L’extrait de code suivant montre un modèle de barrière de base.
// 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
Pour obtenir un exemple complet, consultez Comment : synchroniser des opérations simultanées avec une barrière.
Ajout et suppression de participants
Lorsque vous créez une Barrier instance, spécifiez le nombre de participants. Vous pouvez également ajouter ou supprimer dynamiquement des participants à tout moment. Par exemple, si un participant résout sa partie du problème, vous pouvez stocker le résultat, arrêter l’exécution sur ce thread et appeler Barrier.RemoveParticipant pour décrémenter le nombre de participants dans la barrière. Lorsque vous ajoutez un participant en appelant Barrier.AddParticipant, la valeur de retour spécifie le numéro de phase actuel, qui peut être utile pour initialiser le travail du nouveau participant.
Barrières rompues
Des blocages peuvent se produire si un participant ne parvient pas à atteindre le cloisonnement. Pour éviter ces blocages, utilisez les surcharges de la méthode Barrier.SignalAndWait pour spécifier un délai d'attente et un jeton d'annulation. Ces surcharges retournent une valeur booléenne que chaque participant peut vérifier avant de passer à la phase suivante.
Exceptions post-phase
Si le délégué post-phase lève une exception, il est encapsulé dans un objet BarrierPostPhaseException qui est ensuite propagé à tous les participants.
Barrière contre ContinueWhenAll
Les barrières sont particulièrement utiles lorsque les threads effectuent plusieurs phases dans des boucles. Si votre code ne nécessite qu’une ou deux phases de travail, déterminez s’il faut utiliser System.Threading.Tasks.Task des objets avec n’importe quel type de jointure implicite, notamment :
Pour plus d’informations, consultez Chaînage des tâches à l’aide de tâches de continuation.