Barrier类:
对于同步,Barrier类非常适用于其中工作有多个任务分支且以后又需要合并工作的情况。Barrier类用于需要同步的参与者。激活一个任务时,就可以动态地添加其他参与者,例如,从父任务中创建子任务。参与者在继续之前,可以等待所有其他参与者完成其工作。
static void Main(string[] args)
{
const int numberTasks = 2;
const int partitionSize = 100;
const int loops = 5;
var taskResults = new Dictionary<int, int[][]>();
var data = new List<string>[loops];
for (int i = 0; i < loops; i++)
{
data[i] = new List<string>(FillData(partitionSize * numberTasks));
}
var barrier = new Barrier(numberTasks + 1);
LogBarrierInformation("在屏障的初始参与者", barrier);
for (int i = 0; i < numberTasks; i++)
{
barrier.AddParticipant();
int jobNumber = i;
taskResults.Add(i, new int[loops][]);
for (int loop = 0; loop < loops; loop++)
{
taskResults[i] = new int[loop][];
}
Console.WriteLine($"主任务-正在启动任务作业 {jobNumber}");
Task.Run(() => CalculationInTask(jobNumber, partitionSize, barrier, data, loops, taskResults[jobNumber]));
}
for (int loop = 0; loop < 5; loop++)
{
LogBarrierInformation("主任务,开始发送信号并等待", barrier);
barrier.SignalAndWait();
LogBarrierInformation("主任务等待完成", barrier);
int[][] resultCollection1 = taskResults[0];
int[][] resultCollection2 = taskResults[1];
var resultCollection = resultCollection1[loop].Zip(resultCollection2[loop], (c1, c2) => c1 + c2);
char ch = 'a';
int sum = 0;
foreach (var x in resultCollection)
{
Console.WriteLine($"{ch++},count:{x}");
sum += x;
}
LogBarrierInformation($"main task finished loop {loop},sum:{sum}", barrier);
}
Console.WriteLine("已完成所有迭代");
Console.ReadLine();
}
public static IEnumerable<string> FillData(int size)
{
var r = new Random();
return Enumerable.Range(0, size).Select(x => GetString(r));
}
private static string GetString(Random r)
{
var sb = new StringBuilder(6);
for (int i = 0; i < 6; i++)
{
sb.Append((char)(r.Next(26) + 97));
}
return sb.ToString();
}
private static void LogBarrierInformation(string info, Barrier barrier)
{
Console.WriteLine($"任务 {Task.CurrentId}:{info}.{barrier.ParticipantCount} 当前和 {barrier.ParticipantsRemaining} 剩余参与者阶段 {barrier.CurrentPhaseNumber}");
}
private static void CalculationInTask(int jobNumber, int partitionSize, Barrier barrier, IList<string>[] coll, int loops, int[][] results)
{
LogBarrierInformation("任务中计算已开始", barrier);
for (int i = 0; i < loops; i++)
{
var data = new List<string>(coll[i]);
int start = jobNumber * partitionSize;
int end = start + partitionSize;
Console.WriteLine($"循环{ i}中的任务{ Task.CurrentId}:从{start} 到 {end}");
for (int j = start; j < end; j++)
{
char c = data[j][0];
results[i][c - 97]++;
}
Console.WriteLine($"根据循环{i}中的任务{Task.CurrentId}完成计算. {results[i][0]} 倍的 a,{results[i][25]} 倍的 z");
LogBarrierInformation("发送信号并等待全部", barrier);
barrier.SignalAndWait();
LogBarrierInformation("等待已完成", barrier);
}
barrier.RemoveParticipant();
LogBarrierInformation("已完成任务,已删除参与者", barrier);
}