CountdownEvent
//默认的容纳大小为“硬件线程“数
static CountdownEvent cde = new CountdownEvent(Environment.ProcessorCount);
static void Main(string[] args)
{
//加载User表需要5个任务
var userTaskCount = 5;
cde.Reset(userTaskCount);
for(int i=0;i<userTaskCount;i++)
{
Task.Factory.StartNew((obj) =>
{
LoadUser(obj);
}, i);
}
//等待所有任务执行完毕
cde.Wait();
Console.WriteLine("\nUser表数据全部加载完毕!\n");
var productTaskCount = 8;
cde.Reset(productTaskCount);
for (int i = 0; i < productTaskCount; i++)
{
Task.Factory.StartNew((obj) =>
{
LoadProduct(obj);
}, i);
}
cde.Wait();
Console.WriteLine("\nProduct表数据全部加载完毕!\n");
var orderTaskCount = 8;
cde.Reset(productTaskCount);
for (int i = 0; i < orderTaskCount; i++)
{
Task.Factory.StartNew((obj) =>
{
LoadOrder(obj);
}, i);
}
cde.Wait();
Console.WriteLine("\nOrder表数据全部加载完毕!\n");
Console.WriteLine("\n数据全部加载完毕\n");
Console.ReadKey();
}
private static void LoadUser(object obj)
{
try
{
Console.WriteLine("当前任务:{0}正在加载User部分数据!", obj);
}
finally
{
cde.Signal();
}
}
private static void LoadProduct(object obj)
{
try
{
Console.WriteLine("当前任务:{0}正在加载Product部分数据!", obj);
}
finally
{
cde.Signal();
}
}
private static void LoadOrder(object obj)
{
try
{
Console.WriteLine("当前任务:{0}正在加载Order部分数据!", obj);
}
finally
{
cde.Signal();
}
}
我们看到有两个主要方法:Wait和Signal。每调用一次Signal相当于麻将桌上走了一个人,直到所有人都搓过麻将wait才给放行。
SemaphoreSlim
static SemaphoreSlim slim = new SemaphoreSlim(Environment.ProcessorCount, 12);
static void Main(string[] args)
{
for(int i=0;i<12;i++)
{
Task.Factory.StartNew((obj) =>
{
Run(obj);
}, i);
}
Console.ReadKey();
}
private static void Run(object obj)
{
slim.Wait();
Console.WriteLine("当前时间:{0}任务 {1}已经进入。", DateTime.Now, obj);
Thread.Sleep(3000);
slim.Release();
}
ManualResetEventSlim
这个轻量级别采用的是"自旋等待“+”内核等待“,也就是说先采用”自旋等待的方式“等待,直到另一个任务调用set方法来释放它。如果迟迟等不到释放,那么任务就会进入基于内核的等待,所以说如果我们知道等待的时间比较短,采用轻量级的版本会具有更好的性能,原理大概就这样,下面举个小例子。
static ManualResetEventSlim mrs = new ManualResetEventSlim(false, 2047);
static void Main(string[] args)
{
for(int i=0;i<12;i++)
{
Task.Factory.StartNew((obj) =>
{
Run(obj);
}, i);
}
Console.WriteLine("当前时间:{0}我是主线程{1},你们这些任务都等2s执行吧:\n",
DateTime.Now,
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
mrs.Set();
Console.ReadKey();
}
private static void Run(object obj)
{
mrs.Wait();
Console.WriteLine("当前时间:{0}任务 {1}已经进入。", DateTime.Now, obj);
}