异步多线程Task

Posted johntang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步多线程Task相关的知识,希望对你有一定的参考价值。

Task

概念:

Task线程是基于线程池的,提供了丰富的API

 

Task的启动方式

第一种:

Task task = new Task(() => this.DoSomethingLong("btnTask_Click_1"));

task.Start();

 

第二种:

 Task task = Task.Run(() => this.DoSomethingLong("btnTask_Click_2"));

 

第三种:

 TaskFactory taskFactory = Task.Factory;

 Task task=taskFactory.StartNew(()=> this.DoSomethingLong("btnTask_Click_3"));

 

常用API

Delay

 Sleep同步等待

 Delay异步等待,需要配合ContinueWith()一起使用

Task task = Task.Delay(2000)

    .ContinueWith(t =>

    

        stopwatch.Stop();

);//异步等待--等待2s后启动新任务

 

 

ContinueWhenAny

非阻塞式的回调;而且使用的线程可能是新线程,也可能是刚完成任务的线程,唯一不可能是主线程。创建一个延续Task,它将在提供的组中的任何任务完成后马上开始

语法:

TaskFactory taskFactory = new TaskFactory();

List<Task> taskList = new List<Task>();

taskList.Add(taskFactory.StartNew(() => this.Coding("xxx", "Portal")));

taskFactory.ContinueWhenAny(

taskList.ToArray(),t=>Console.WriteLie()

);

 

ContinueWhenAll

非阻塞式的回调;而且使用的线程可能是新线程,也可能是刚完成任务的线程,唯一不可能是主线程。创建一个延续任务,该任务在一组指定的任务完成后开始

语法:

TaskFactory taskFactory = new TaskFactory();

List<Task> taskList = new List<Task>();

taskList.Add(taskFactory.ContinueWhenAll(taskList.ToArray(), rArray => Console.WriteLine()));

 

WaitAny

阻塞当前线程,等着任意一个任务完成

Task.WaitAny(taskList.ToArray());//也可以限时等待

 

WaitAll

需要能够等待全部线程完成任务再继续  阻塞当前线程,等着全部任务完成

Task.WaitAll(taskList.ToArray());

 

ContinueWith

回调,创建一个目标在task完成时异步执行的延续任务

Task.Run(() => this.DoSomethingLong("btnTask_Click"))

.ContinueWith(t => Console.WriteLine());//回调

 

 

完整示例代码

          #region Task启动
            
                ////Task启动方式一
                //Task task = new Task(() => Console.WriteLine("buttonTask_Click"));
                //task.Start();
                ////Task启动方式二
                //Task taskRun = Task.Run(() => Console.WriteLine("buttonTask_Click"));
                ////Task启动方式三
                //TaskFactory taskFactory = new TaskFactory();
                //Task task2 = taskFactory.StartNew(() => Console.WriteLine("buttonTask_Click"));
            
            #endregion

            #region Delay 异步等待
            
                ////Delay 异步等待 通常是配合ContinueWith()一起使用
                ////Sleep同步等待
                ////ContinueWhenAny:回调,创建一个目标在task完成时异步执行的延续任务
                //Stopwatch stopwatch = new Stopwatch();
                ////异步等待,不会阻塞
                //Task task = Task.Delay(2000).ContinueWith(t=> 
                //
                //    stopwatch.Stop();
                //    Console.WriteLine("这是Delay"+"运行时间:"+stopwatch.Elapsed);

                //);
                //Console.WriteLine("这是Delay等待之后的方法");               
            
            #endregion

            #region ContinueWhenAny非阻塞的回调
            //
            //    //创建一个延续Task,它将在提供的组中的任何任务完成后马上开始
            //    TaskFactory taskFactory = new TaskFactory();
            //    List<Task> taskList = new List<Task>();
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张三", "ContinueWhenAny 01")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张四", "ContinueWhenAny 02")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张五", "ContinueWhenAny 03")));
            //    taskFactory.ContinueWhenAny(taskList.ToArray(), t => 

            //        Console.WriteLine("另外一个方法");
            //    );

            //
            #endregion

            #region ContinueWhenAll 非阻塞的回调

            //
            //    //创建一个延续Task,它将在提供的组中的所有任务完成后马上开始
            //    TaskFactory taskFactory = new TaskFactory();
            //    List<Task> taskList = new List<Task>();
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张三", "ContinueWhenAny 01")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张四", "ContinueWhenAny 02")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张五", "ContinueWhenAny 03")));
            //    taskFactory.ContinueWhenAll(taskList.ToArray(), t =>
            //    

            //        Console.WriteLine("另外一个方法2");
            //    );

            //
            #endregion

            #region WaitAny 阻塞当前线程,等着任意一个任务完成
            //

            //    List<Task> taskList = new List<Task>();
            //    TaskFactory taskFactory = new TaskFactory();
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张三", "WaitAny 01")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("李四", "WaitAny 02")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("王五", "WaitAny 03")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("赵六", "WaitAny 04")));
            //    Task.WaitAny(taskList.ToArray());
            //    Console.WriteLine("我是另一个方法");

            //
            #endregion

            #region WaitAll 阻塞当前线程,等着所有任务完成
            //

            //    List<Task> taskList = new List<Task>();
            //    TaskFactory taskFactory = new TaskFactory();
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("张三", "WaitAny 01")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("李四", "WaitAny 02")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("王五", "WaitAny 03")));
            //    taskList.Add(taskFactory.StartNew(() => this.Coding("赵六", "WaitAny 04")));
            //    Task.WaitAll(taskList.ToArray());
            //    Console.WriteLine("我是另一个方法");

            //
            #endregion


            #region  ContinueWith 创建一个目标在task完成时异步执行的延续任务
            //
            //    Task.Run(() => 
            //        Console.WriteLine("ContinueWith1");
            //        Console.WriteLine("ContinueWith11");
            //        Console.WriteLine("ContinueWith111");
            //    ).ContinueWith(t=> 
            //        Console.WriteLine("ContinueWith2");
            //        Console.WriteLine("ContinueWith22");
            //        Console.WriteLine("ContinueWith222");
            //    );
            //
            #endregion

            #region 扩展 控制Task的并发数量
            
                //假如说我想控制下Task的并发数量,该怎么做?5个
                //准备一个Task容器
                List<Task> taskList = new List<Task>();
                //实例化TaskFactory
                TaskFactory taskFactory = new TaskFactory();
                taskList.Add(taskFactory.StartNew(() => Console.WriteLine("张三" + "," + "WaitAny 01")));
                taskList.Add(taskFactory.StartNew(() => Console.WriteLine("李四" + "," + "WaitAny 02")));
                taskList.Add(taskFactory.StartNew(() => Console.WriteLine("王五" + "," + "WaitAny 03")));
                taskList.Add(taskFactory.StartNew(() => Console.WriteLine("赵六" + "," + "WaitAny 04")));

                for (int i = 0; i < 10; i++)
                
                    int k = i;
                    //t.Status != TaskStatus.RanToCompletion
                    //如果taskList里不成功的线程数量大于5
                    if (taskList.Count(t => t.Status != TaskStatus.RanToCompletion) >= 5)
                    
                        Task.WaitAny(taskList.ToArray());
                        taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
                    
                    taskList.Add(Task.Run(() =>
                    
                        Console.WriteLine($"This is k running ThreadId=Thread.CurrentThread.ManagedThreadId.ToString("00")");
                        Thread.Sleep(2000);
                    ));
                
            
            #endregion

 

以上是关于异步多线程Task的主要内容,如果未能解决你的问题,请参考以下文章

C# Task总结(异步操作+并行)

C#多线程和异步——Task和async/await详解

异步多线程之入Task详解

多线程

聊聊多线程那一些事儿(task)之 三 异步取消和异步方法

C#/.NET 多线程任务Task的详解——应用实例