有这样一个题目:四个线程t1,t2,t3,t4,向4个文件中写入数据,要求:t1只能写入“1”,t2只能写入“2”,t3只能写入“3”,t4只能写入“4”,对4个文件A,B,C,D写入如下内容:
  A:123412341234.....
  B:234123412341....
  C:341234123412....
  D:412341234123....
  简单分析一下,对于A文件,t1写入“1”后,我们希望通知t2来写“2”,并且t1前往D文件等着去写“1”,以此类推。
  1. 通过等待句柄实现
  显然可以用等待句柄来实现,通知t2来写“2”相当于在一个等待句柄上调用 Set 方法,等待在D文件上写“1”相当于在另一等待句柄上调用了 WaitOne 方法,下边是利用4个 AutoResetEvent 来实现它:
class Program
{
private static List<StreamWriter> _sws;
private static List<AutoResetEvent> _whs;
private static void Main(string[] args)
{
var fileNames = new List<string> {"A", "B", "C", "D"};
// 创建或清空文件
fileNames.ForEach(name =>
{
if (!File.Exists(name))
File.Create(name).Close();
else
{
using (var sw = new StreamWriter(name))
sw.Write("");
}
});
_sws = fileNames.Select(File.AppendText).ToList();
// 为每个文件写入建立一个等待句柄
_whs = fileNames.Select(name => new AutoResetEvent(false)).ToList();
// 创建并启4个线程执行任务
var threads = new List<Thread> {
new Thread(() => Work(1)), new Thread(() => Work(2)), new Thread(() => Work(3)), new Thread(() => Work(4))
};
threads.ForEach(t => t.Start());
// 等待线程结束并关闭 StreamWrite
threads.ForEach(t => t.Join());
Console.WriteLine("任务完成!");
_sws.ForEach(sw => sw.Close());
}
static void Work(int threadIndex)
{
var next = threadIndex - 1;
// 为让程序能结束,打印100次
for (int i = 0; i < 100; i++)
{
var wh = _whs[next];
var sw = _sws[next];
lock (sw)
{
sw.Write(threadIndex);
}
next = (next - 1) < 0 ? 3 : next - 1;
WaitHandle.SignalAndWait(wh, _whs[next]);  //在wh上发信号,并在下一个等待句柄上等待执行
}
}
}
  上述例子中我们创建了4个线程来分别打印1,2,3,4,并且为每个文件的写入创建了4个等待句柄来进行信号通信。后主线程在等待所有线程结束后,关闭文件流。为让程序能正常结束,在 Work 方法中只循环写100次。
  以t1(列表中第一个线程)为例,在A文件中打印1后,调用 WaitHandle.SignalAndWait(wh,wh[next]),即在wh上发信号通知可以接着写入了,并在下一个等待句柄上等待写入信号。
  关于 SinalAndWait 的可以参见 Thread in C# 或者对应的 中文翻译 。