理解
Barrier与ContinueWith都是用于并发编程的工具,但它们的设计目的和应用场景有本质区别。Barrier侧重于多线程间的同步协调,而ContinueWith则用于定义异步操作完成后的后续动作。
Barrier 是一个同步原语,用于协调多个线程的执行进度。它像一道关卡,所有参与的线程必须到达屏障点后等待,直到所有线程都到达,才能同时通过并继续执行。这通常用于需要阶段性同步的并行算法,例如在多轮迭代计算中确保所有线程完成当前阶段后再进入下一阶段。Barrier 支持多阶段操作,并允许在每个阶段完成后执行回调动作。其核心方法 SignalAndWait() 使当前线程通知屏障自己已到达并等待其他线程。如果某个线程未调用此方法,会导致死锁。
ContinueWith 是Task类的一个方法,用于定义异步操作完成后的后续操作。当一个任务(Task)执行完毕时,可以指定一个委托(Action或Func)通过 ContinueWith 来执行,这类似于"链式调用"或回调机制。它常用于处理异步操作的结果或执行清理工作,例如在文件读取完成后更新UI或处理数据。 ContinueWith 不涉及线程同步,而是专注于异步流程的编排。
两者的主要区别在于:
- 作用范围:Barrier 用于多线程间的同步,确保线程在特定点对齐;ContinueWith 用于单个异步任务的后续操作链。
- 使用场景:Barrier 适用于需要所有线程协作的并行计算(如迭代算法);ContinueWith 适用于异步编程中的流程控制(如I/O操作后的处理)。
- 同步机制:Barrier 是阻塞式同步,线程会等待其他线程到达;ContinueWith 是非阻塞的,任务完成后自动触发后续操作。
在实际编程中,如果需要协调多个线程的阶段性执行,应选择 Barrier;如果需要定义异步操作的后续步骤,则应使用 ContinueWith。两者可以结合使用,例如在 Barrier 的阶段回调中启动新的异步任务,但它们的核心职责不同。
实例
cs
internal class Program
{
static string[] words1 = new string[] { "brown", "jumps", "the", "fox", "quick" };
static string[] words2 = new string[] { "dog", "lazy", "the", "over" };
static string solution = "the quick brown fox jumps over the lazy dog.";
static bool success = false;
static Barrier barrier = new Barrier(2, (b) =>
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < words1.Length; i++)
{
sb.Append(words1[i]);
sb.Append(" ");
}
for (int i = 0; i < words2.Length; i++)
{
sb.Append(words2[i]);
if (i < words2.Length - 1)
sb.Append(" ");
}
sb.Append(".");
#if TRACE
System.Diagnostics.Trace.WriteLine(sb.ToString());
#endif
Console.CursorLeft = 0;
Console.Write("Current phase: {0}", barrier.CurrentPhaseNumber);
if (String.CompareOrdinal(solution, sb.ToString()) == 0)
{
success = true;
Console.WriteLine($"\r\nThe solution was found in {barrier.CurrentPhaseNumber} attempts");
}
});
static void Main(string[] args)
{
Thread t1 = new Thread(() => Solve(words1));
Thread t2 = new Thread(() => Solve(words2));
t1.Start();
t2.Start();
Console.ReadLine();
}
static void Solve(string[] wordArray)
{
while (success == false)
{
Random random = new Random();
for (int i = wordArray.Length - 1; i > 0; i--)
{
int swapIndex = random.Next(i + 1);
string temp = wordArray[i];
wordArray[i] = wordArray[swapIndex];
wordArray[swapIndex] = temp;
}
barrier.SignalAndWait();
}
}
}