System.Threading.Barrier是同步處理基本類型,可讓多個線程(稱為參與者)分階段在演算法上同時運作。 每個參與者都會執行,直到到達程序代碼中的屏障點為止。 屏障代表工作一個階段的結尾。 當參與者到達屏障時,它會封鎖,直到所有參與者都達到相同的屏障為止。 所有參與者都到達屏障之後,您可以選擇性地叫用後續階段的動作。 這個後續階段動作可用來執行單個線程的動作,而所有其他線程仍會遭到封鎖。 執行動作之後,參與者全都會解除封鎖。
下列代碼段顯示基本屏障模式。
// 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
如需完整的範例,請參閱 如何:同步處理並行作業與屏障。
新增和移除參與者
當您建立 Barrier 實例時,請指定參與者的數目。 您也可以隨時動態新增或移除參與者。 例如,如果某個參與者解決問題,您可以儲存結果、停止在該線程上執行,並呼叫 Barrier.RemoveParticipant 來遞減屏障中的參與者數目。 當您藉由呼叫 Barrier.AddParticipant來新增參與者時,傳回值會指定目前的階段號碼,這可能有助於初始化新參與者的工作。
破碎的屏障
如果一個參與者無法到達屏障,就會發生死結。 若要避免這些死結,請使用 Barrier.SignalAndWait 方法的重載來指定超時時間和取消令牌。 這些多載會傳回布爾值,讓每個參與者在繼續下一個階段之前先檢查該值。
階段后例外狀況
如果後階段委派擲回例外狀況,它會被包裝在BarrierPostPhaseException 物件中,然後傳播至所有參與者。
屏障與 ContinueWhenAll
當線程在迴圈中執行多個階段時,屏障特別有用。 如果您的程式碼只需要一或兩個階段的工作,請考慮是否要使用 System.Threading.Tasks.Task 物件,這些物件包括任何類型的隱式聯結:
如需詳細資訊,請參閱使用接續工作鏈結任務。