执行结果如下:


可以看到,刚开始只有三个线程在执行,当一个线程执行完毕并释放之后,才会有新的线程来执行方法!
除了SemaphoreSlim类,还可以使用Semaphore类,感觉更加灵活,感兴趣的话可以搜一下,这里就不做演示了!
2.Task
Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程。
Console.WriteLine("主线程启动");
//Task.Run启动一个线程
//Task启动的是后台线程,要在主线程中等待后台线程执行完毕,可以调用Wait方法
//Task task = Task.Factory.StartNew(() => { Thread.Sleep(1500); Console.WriteLine("task启动"); });
Task task = Task.Run(() => {
Thread.Sleep(1500);
Console.WriteLine("task启动");
});
Thread.Sleep(300);
task.Wait();
Console.WriteLine("主线程结束");
执行结果如下:

开启新任务的方法:Task.Run()或者Task.Factory.StartNew(),开启的是后台线程
要在主线程中等待后台线程执行完毕,可以使用Wait方法(会以同步的方式来执行)。不用Wait则会以异步的方式来执行。
比较一下Task和Thread:
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
new Thread(Run1).Start();
}
for (int i = 0; i < 5; i++)
{
Task.Run(() => { Run2(); });
}
}
static void Run1()
{
Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);
}
static void Run2()
{
Console.WriteLine("Task调用的Thread Id =" + Thread.CurrentThread.ManagedThreadId);
}
执行结果:

可以看出来,直接用Thread会开启5个线程,用Task(用了线程池)开启了3个!
2.1 Task<TResult>
Task<TResult>就是有返回值的Task,TResult就是返回值类型。
Console.WriteLine("主线程开始");
//返回值类型为string
Task<string> task = Task<string>.Run(() => {
Thread.Sleep(2000);
return Thread.CurrentThread.ManagedThreadId.ToString();
});
//会等到task执行完毕才会输出;
Console.WriteLine(task.Result);
Console.WriteLine("主线程结束");










