C#多线程学习笔记四

Task简介

为什么要有Task?
Thread:容易造成时间和空间的开销,而且使用不当容易造成线程过多,导致时间片切换
ThreadPool:控制能力比较弱,比如做Thread的延续,阻塞,取消,超时等功能不能实现,ThreadPool的控制权在CLR,而不在自己。
Task => Thread + ThreadPool + 优化 + 功能扩展
Task看起来像一个Thread,但是在ThreadPool的基础上进行封装并做了性能优化。.net 4.0之后,微软极力推荐Task作为异步计算。

Task的启动方式

启动方式一:实例化方式启动Task

Task task = new Task(()=> 
{
    
    
Console.WriteLine("tid={0}", Thread.CurrentThread.ManagedThreadId);
});
task.Start();

启动方式二:TaskFactory的方式启动Task

var task = Task.Factory.StartNew(()=> 
{
    
    
Console.WriteLine("tid={0}", Thread.CurrentThread.ManagedThreadId);
});

启动方式三:Task.Run()的方式启动Task

var task = Task.Run(()=> 
{
    
    
Console.WriteLine("tid={0}", Thread.CurrentThread.ManagedThreadId);
});

启动方式四:同步执行Task

Task task = new Task(()=> 
{
    
    
Console.WriteLine("tid={0}", Thread.CurrentThread.ManagedThreadId);
});
task.RunSynchronously ();

Task和ThreadPool

Task底层是由不同的TaskSchedule支撑的,TaskSchedule相当于Task的CPU。默认的TaskSchedule是ThreadPoolScheduler,WPF中的TaskSchedule是SynchronizationContextTaskScheduler, TaskSchedule可以自己定义。

Task的阻塞和延续

阻塞

有以下两个task

Task task1 = new Task(()=> 
{
    
    
Thread.Sleep(1000);
    Console.WriteLine("t1"); 
});
Task task2 = new Task(() =>
{
    
    
Thread.Sleep(2000);
    Console.WriteLine("t2"); 
});
task1.Start();
task2.Start();
var tasks = new Task[2] {
    
     task1, task2 };

(1)WaitAll方法 必须其中所有的Task执行完成才算完成

Task.WaitAll(tasks);
Console.WriteLine("main");

输出顺序为:t1 t2 main

(2)WaitAny方法 只要其中一个Task执行完成就算完成

Task.WaitAny(tasks);
Console.WriteLine("main");

输出顺序为:t1 main t2。

(3)Wait方法 等待操作,用法和效果等同于thread.Join()

上面三个方法的返回值都是void。那么,如果不想阻塞主线程实现WaitAll操作,该怎么做?
t1 t2执行完了执行t3,这就是延续的概念。

阻塞

(1)WhenAll方法

Task.WhenAll(tasks).ContinueWith(new Action<Task>(t=> 
{
    
     
Console.WriteLine("t3"); 
}));

输出顺序为:t1 t2 t3。且主线程没有被阻塞。

(2)WhenAny方法

Task.WhenAny(tasks).ContinueWith(new Action<Task>(t=> 
{
    
     
Console.WriteLine("t3"); 
}));

输出顺序为:t1 t3 t2。且主线程没有被阻塞。

(3)ContinueWhenAll方法:效果同WhenAll

Task.Factory.ContinueWhenAll(tasks, t => 
{
    
     
Console.WriteLine("t3"); 
});

(4)ContinueWhenAny方法:效果同WhenAny

Task.Factory.ContinueWhenAny(tasks, t => 
{
    
     
Console.WriteLine("t3"); 
});

猜你喜欢

转载自blog.csdn.net/Z960515/article/details/113436177