zoukankan      html  css  js  c++  java
  • 多线程教程(三):Task

    一、基本概念

    1、Task优势

    ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便,例如:

    • ThreadPool不支持线程的取消、完成、失败通知等交互性操作;
    • ThreadPool不支持线程执行的先后次序;

    .NET Framework 在4.0的时候提供了一个功能更强大的概念:Task。Task在ThreadPool的基础上进行了优化,并提供了更多的API。看下面一个简单的示例:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                // 创建Task
                Task t = new Task(() => 
                {
                    Console.WriteLine("任务开始工作.....");
                    Thread.Sleep(5000);
                });
                // 启动
                t.Start();
                t.ContinueWith((task) => 
                {
                    Console.WriteLine("任务完成,完成时候的状态为:");
                    Console.WriteLine("IsCanceled={0}	IsCompleted={1}	IsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
                });
                Console.WriteLine("启动");
                Console.ReadKey();
            }
        }
    }

    二、Task用法

    2.1、创建任务

    Task创建的任务可以分为有返回值和无返回值两种。

    1、使用Task创建无返回值

    先看一下Task的定义:

    可以看到Task构造函数的参数是Action委托。所以使用Task创建任务的代码如下:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                #region 1、使用Task创建任务
                Task task = new Task(() => TaskMethod("Task 1"));
                Console.WriteLine("before start status:"+task.Status);
                // Task创建的任务必须调用start方法才能启动
                task.Start();
                Console.WriteLine("after start status:" + task.Status);
                #endregion
                Console.ReadKey();
            }
    
            static void TaskMethod(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                    name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            }
        }
    }

    程序运行结果:

    注:任务的状态,Start之前为Created,Start之后为WaitingToRun。

    2、使用Task.Run方法创建任务

    Task.Run创建的任务可以执行启动:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                #region 1、使用Task创建任务
                //Task task = new Task(() => TaskMethod("Task 1"));
                //Console.WriteLine("before start status:"+task.Status);
                //// Task创建的任务必须调用start方法才能启动
                //task.Start();
                //Console.WriteLine("after start status:" + task.Status);
                #endregion
    
                #region 2、使用Task.Run创建任务
                Task.Run(() => TaskMethod("Task Run"));
                #endregion
                Console.ReadKey();
            }
    
            static void TaskMethod(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                    name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            }
        }
    }

    程序运行结果:

    3、使用Factory方式创建任务

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                #region 1、使用Task创建任务
                //Task task = new Task(() => TaskMethod("Task 1"));
                //Console.WriteLine("before start status:"+task.Status);
                //// Task创建的任务必须调用start方法才能启动
                //task.Start();
                //Console.WriteLine("after start status:" + task.Status);
                #endregion
    
                #region 2、使用Task.Run创建任务
                // Task.Run(() => TaskMethod("Task Run"));
                #endregion
    
                #region 3、使用Factory创建任务
                // 使用Task.Factory创建
                Task.Factory.StartNew(() => TaskMethod("Task 4"));
                //标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
                Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
    
                // 实例化TaskFactory对象,然后创建
                TaskFactory factory = new TaskFactory();
                factory.StartNew(() => TaskMethod("Task 6"));
    
    
                #endregion
                Console.ReadKey();
            }
    
            static void TaskMethod(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                    name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            }
        }
    }

    程序运行结果:

    4、创建带返回值的Task

    代码如下:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                #region 1、使用Task创建任务
                //Task task = new Task(() => TaskMethod("Task 1"));
                //Console.WriteLine("before start status:"+task.Status);
                //// Task创建的任务必须调用start方法才能启动
                //task.Start();
                //Console.WriteLine("after start status:" + task.Status);
                #endregion
    
                #region 2、使用Task.Run创建任务
                // Task.Run(() => TaskMethod("Task Run"));
                #endregion
    
                #region 3、使用Task.Factory创建任务
                //Task.Factory.StartNew(() => TaskMethod("Task 4"));
                ////标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
                //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
                #endregion
    
                #region 4、创建带返回值的任务
                TaskMethodReturn("Main Thread Task");
                // 创建带返回值的Task
                Task<int> task = CreateTask("Task 1");
                // 启动
                task.Start();
                // 获取返回值
                int result1 = task.Result;
                Console.WriteLine($"Task 1 Result is:{result1}");
                Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2"));
                task2.Start();
                int result2 = task2.Result;
                Console.WriteLine($"Task 2 Result is:{result2}");
                int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result;
                Console.WriteLine($"Task 3 Result is:{result3}");
                int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result;
                Console.WriteLine($"Task 4 Result is:{result4}");
                #endregion
                Console.ReadKey();
            }
    
            /// <summary>
            /// 返回一个Task<int>
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            static Task<int> CreateTask(string name)
            {
                // 参数是Func<int>
                return new Task<int>(() => TaskMethodReturn(name));
            }
    
            static void TaskMethod(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                    name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            }
    
            static int TaskMethodReturn(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                       name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
                Thread.Sleep(TimeSpan.FromSeconds(2));
                return 42;
            }
        }
    }

    程序运行结果:

    我们在文章开始的时候说过,Task是基于ThreadPool的,那么怎么证明呢?看下面的代码:

    /// <summary>
    /// 测试Task的线程来自于ThreadPool
    /// </summary>
    static void Test()
    {
                // 设置线程池中最大的线程数
                ThreadPool.SetMaxThreads(6, 6);
                // 创建Task的集合
                List<Task> taskList = new List<Task>();
                // 创建int类型的集合,用于存放线程ID
                List<int> threadIdList = new List<int>();
                // 使用Task循环创建50个线程
                for (int i = 0; i < 30; i++)
                {
                    int k = i;
                    Task task = Task.Run(() => 
                    {
                        // 当前线程ID加入到集合中
                        threadIdList.Add(Thread.CurrentThread.ManagedThreadId);
                        Console.WriteLine($"this is {k} 循环 ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                        // 休眠
                        Thread.Sleep(200);
                    });
                    // 把task加入到集合中
                    taskList.Add(task);
                }
    
                // 等待所有的线程执行完
                Task.WaitAll(taskList.ToArray());
                // 输出总数量
                Console.WriteLine($"线程总数:{threadIdList.Distinct().Count()}");
    }

    程序运行结果:

    从结果中可以看出,Task中的线程确实是来自于ThreadPool。

    三、常见方法

    我们以下面的一个例子来讲解Task中比较常见的几个方法。多名开发者合作开发一个项目,每个人负责一个模块的开发,我们可以把这个过程认为是多线程,代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                #region 1、使用Task创建任务
                //Task task = new Task(() => TaskMethod("Task 1"));
                //Console.WriteLine("before start status:"+task.Status);
                //// Task创建的任务必须调用start方法才能启动
                //task.Start();
                //Console.WriteLine("after start status:" + task.Status);
                #endregion
    
                #region 2、使用Task.Run创建任务
                // Task.Run(() => TaskMethod("Task Run"));
                #endregion
    
                #region 3、使用Factory创建任务
                // 使用Task.Factory创建
                //Task.Factory.StartNew(() => TaskMethod("Task 4"));
                ////标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
                //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
    
                // 实例化TaskFactory对象,然后创建
                //TaskFactory factory = new TaskFactory();
                //factory.StartNew(() => TaskMethod("Task 6"));
                #endregion
    
                #region 4、创建带返回值的任务
                //TaskMethodReturn("Main Thread Task");
                //// 创建带返回值的Task
                //Task<int> task = CreateTask("Task 1");
                //// 启动
                //task.Start();
                //// 获取返回值
                //int result1 = task.Result;
                //Console.WriteLine($"Task 1 Result is:{result1}");
                //Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2"));
                //task2.Start();
                //int result2 = task2.Result;
                //Console.WriteLine($"Task 2 Result is:{result2}");
                //int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result;
                //Console.WriteLine($"Task 3 Result is:{result3}");
                //int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result;
                //Console.WriteLine($"Task 4 Result is:{result4}");
                #endregion
    
    
                #region 测试Task线程是来自于ThreadPool
    
                // Test();
                #endregion
    
                // 合作开发项目,每个人负责一个模块,可以认为是多线程
                Console.WriteLine("开始合作开发一个大项目!");
                Task.Run(() => CodingShow("Tom", "搭建微服务架构!"));
                Task.Run(() => CodingShow("Kevin", "微信接口!"));
                Task.Run(() => CodingShow("Jack", "搭建后台框架!"));
                Task.Run(() => CodingShow("Alex", "设计数据库!"));
                Task.Run(() => CodingShow("Lee", "支付宝接口对接!"));
    
    
    
    
    
                Console.ReadKey();
            }
    
            /// <summary>
            /// 返回一个Task<int>
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            static Task<int> CreateTask(string name)
            {
                // 参数是Func<int>
                return new Task<int>(() => TaskMethodReturn(name));
            }
    
            static void TaskMethod(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                    name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            }
    
            static int TaskMethodReturn(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                       name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
                Thread.Sleep(TimeSpan.FromSeconds(2));
                return 42;
            }
    
            /// <summary>
            /// 测试Task的线程来自于ThreadPool
            /// </summary>
            static void Test()
            {
                // 设置线程池中最大的线程数
                ThreadPool.SetMaxThreads(6, 6);
                // 创建Task的集合
                List<Task> taskList = new List<Task>();
                // 创建int类型的集合,用于存放线程ID
                List<int> threadIdList = new List<int>();
                // 使用Task循环创建50个线程
                for (int i = 0; i < 30; i++)
                {
                    int k = i;
                    Task task = Task.Run(() =>
                    {
                        // 当前线程ID加入到集合中
                        threadIdList.Add(Thread.CurrentThread.ManagedThreadId);
                        Console.WriteLine($"this is {k} 循环 ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                        // 休眠
                        Thread.Sleep(200);
                    });
                    // 把task加入到集合中
                    taskList.Add(task);
                }
    
                // 等待所有的线程执行完
                Task.WaitAll(taskList.ToArray());
                // 输出总数量
                Console.WriteLine($"线程总数:{threadIdList.Distinct().Count()}");
            }
    
            /// <summary>
            /// 模拟Coding过程
            /// </summary>
            /// <param name="name"></param>
            /// <param name="projectName"></param>
            static void CodingShow(string name, string projectName)
            {
                Console.WriteLine($"CodingShow Start  {name} {projectName}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
                long lResult = 0;
                for (int i = 0; i < 1_000_000_000; i++)
                {
                    lResult += i;
                }
    
                Console.WriteLine($"CodingShow   End  {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
            }
        }
    }

    程序运行结果:

    这时需求发生了变化,所有的模块都开发完成以后,开始搭建测试环境,修改代码如下:

    // 合作开发项目,每个人负责一个模块,可以认为是多线程
    Console.WriteLine("开始合作开发一个大项目!");
    Task.Run(() => CodingShow("Tom", "搭建微服务架构!"));
    Task.Run(() => CodingShow("Kevin", "微信接口!"));
    Task.Run(() => CodingShow("Jack", "搭建后台框架!"));
    Task.Run(() => CodingShow("Alex", "设计数据库!"));
    Task.Run(() => CodingShow("Lee", "支付宝接口对接!"));
    Console.WriteLine("所有模块都开发完成,开始搭建测试环境");

    程序运行结果:

    可以看到显然不是我们想要的结果,模块开发工作还没有结束就搭建测试环境,即子线程还没有结束,主线程就已经结束了。要想实现我们想要的效果,那么必须使主线程等待所有子线程都结束以后,主线程才能结束。

    1、WaitAll()

    WaitAll()表示等待所有的Task都执行完成。看WaitAll()的定义:

     WaitAll()方法有很多重载,我们在这里使用第一个重载方法,即参数是Task[]数组。查看Run()方法的定义时,我们会发现Run()方法的返回值就是Task类型,我们使用WaitAll()修改上面的代码:

    // 定义一个Task类型的集合
    List<Task> taskList = new List<Task>();
    Console.WriteLine("开始合作开发一个大项目!");
    taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
    taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
    taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
    taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
    taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
    
    // 等待所有模块都开发完成,才能搭建测试环境
    Task.WaitAll(taskList.ToArray());
    Console.WriteLine("所有模块都开发完成,开始搭建测试环境");

    程序运行结果:

    WaitAll()会使程序产生卡顿。

    加载首页信息的时候可以使用WaitAll()方法。一个首页信息可能来自于几部分的数据,每一部分的数据对应一个线程,只有所有的线程都执行完毕才显示首页信息。

    2、WaitAny()

    这时需求又发生改变了:某一个模块开发完成以后就搭建测试环境。这时候就可以使用WaitAny()了。WaitAny()表示等待其中任何一个任务完成就会进入下一个任务,定义如下:

    修改后的代码如下:

    // 定义一个Task类型的集合
    List<Task> taskList = new List<Task>();
    Console.WriteLine("开始合作开发一个大项目!");
    taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
    taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
    taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
    taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
    taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
    
    // 等待所有模块都开发完成,才能搭建测试环境
    Task.WaitAny(taskList.ToArray());
    Console.WriteLine("有模块开发完成,开始搭建测试环境");

    程序运行结果:

    可以看到:设计数据库模块完成以后,就开始搭建测试环境了。如何需求。

    WaitAny()会使程序产生卡顿。

    有一个列表数据,数据可以来源于接口、缓存、数据库等,可以开启多个线程,只要有一个线程执行完毕就可以继续执行下面的步骤,这时就可以使用WaitAny()。

    3、ContinueWhenAll()

    WaitAll()会卡顿界面,那么有没有不卡顿界面的呢?ContinueWhenAll和WaitAll实现的效果一样,代码如下:

    List<Task> taskList = new List<Task>();
    Console.WriteLine("开始合作开发一个大项目!");
    taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
    taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
    taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
    taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
    taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
    TaskFactory factory = new TaskFactory();
    factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模块开发完成"));

    程序运行结果:

    4、ContinueWhenAny

    ContinueWhenAny实现的效果和WaitAny一样,ContinueWhenAny不会卡顿界面,代码如下:

    List<Task> taskList = new List<Task>();
    Console.WriteLine("开始合作开发一个大项目!");
    taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
    taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
    taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
    taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
    taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
    TaskFactory factory = new TaskFactory();
    factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一个模块开发完成"));

    程序运行结果:

    ContinueWhenAll()和ContinueWhenAny()都会开启一个新的线程。

    5、ContinueWith

    ContinueWith表示回调,代码如下:

    Task.Run(() => { Console.WriteLine("任务执行完成"); }).ContinueWith(p=> 
    {
          Task.Run(() => { Console.WriteLine("执行回调"); });
    });

    程序执行结果:

    程序完整代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TaskDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                #region 1、使用Task创建任务
                //Task task = new Task(() => TaskMethod("Task 1"));
                //Console.WriteLine("before start status:"+task.Status);
                //// Task创建的任务必须调用start方法才能启动
                //task.Start();
                //Console.WriteLine("after start status:" + task.Status);
                #endregion
    
                #region 2、使用Task.Run创建任务
                // Task.Run(() => TaskMethod("Task Run"));
                #endregion
    
                #region 3、使用Factory创建任务
                // 使用Task.Factory创建
                //Task.Factory.StartNew(() => TaskMethod("Task 4"));
                ////标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
                //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
    
                // 实例化TaskFactory对象,然后创建
                //TaskFactory factory = new TaskFactory();
                //factory.StartNew(() => TaskMethod("Task 6"));
                #endregion
    
                #region 4、创建带返回值的任务
                //TaskMethodReturn("Main Thread Task");
                //// 创建带返回值的Task
                //Task<int> task = CreateTask("Task 1");
                //// 启动
                //task.Start();
                //// 获取返回值
                //int result1 = task.Result;
                //Console.WriteLine($"Task 1 Result is:{result1}");
                //Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2"));
                //task2.Start();
                //int result2 = task2.Result;
                //Console.WriteLine($"Task 2 Result is:{result2}");
                //int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result;
                //Console.WriteLine($"Task 3 Result is:{result3}");
                //int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result;
                //Console.WriteLine($"Task 4 Result is:{result4}");
                #endregion
    
    
                #region 测试Task线程是来自于ThreadPool
    
                // Test();
                #endregion
    
                // 合作开发项目,每个人负责一个模块,可以认为是多线程
                // 无序
                //Console.WriteLine("开始合作开发一个大项目!");
                //Task.Run(() => CodingShow("Tom", "搭建微服务架构!"));
                //Task.Run(() => CodingShow("Kevin", "微信接口!"));
                //Task.Run(() => CodingShow("Jack", "搭建后台框架!"));
                //Task.Run(() => CodingShow("Alex", "设计数据库!"));
                //Task.Run(() => CodingShow("Lee", "支付宝接口对接!"));
                //Console.WriteLine("所有模块都开发完成,开始搭建测试环境");
    
                #region WaitAll
                //// 定义一个Task类型的集合
                //List<Task> taskList = new List<Task>();
                //Console.WriteLine("开始合作开发一个大项目!");
                //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
                //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
                //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
                //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
                //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
    
                //// 等待所有模块都开发完成,才能搭建测试环境
                //Task.WaitAll(taskList.ToArray());
                //Console.WriteLine("所有模块都开发完成,开始搭建测试环境");
                #endregion
    
                #region WaitAny
                // 定义一个Task类型的集合
                //List<Task> taskList = new List<Task>();
                //Console.WriteLine("开始合作开发一个大项目!");
                //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
                //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
                //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
                //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
                //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
    
                //// 等待所有模块都开发完成,才能搭建测试环境
                //Task.WaitAny(taskList.ToArray());
                //Console.WriteLine("有模块开发完成,开始搭建测试环境");
                #endregion
    
                #region ContinueWhenAll
                //List<Task> taskList = new List<Task>();
                //Console.WriteLine("开始合作开发一个大项目!");
                //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
                //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
                //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
                //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
                //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
                //TaskFactory factory = new TaskFactory();
                //factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模块开发完成"));
                #endregion
    
                #region ContinueWhenAll
                //List<Task> taskList = new List<Task>();
                //Console.WriteLine("开始合作开发一个大项目!");
                //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!")));
                //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
                //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!")));
                //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!")));
                //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!")));
                //TaskFactory factory = new TaskFactory();
                //factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一个模块开发完成"));
                #endregion
    
                #region ContinueWith
                Task.Run(() => { Console.WriteLine("任务执行完成"); }).ContinueWith(p=> 
                {
                   Task.Run(() => { Console.WriteLine("执行回调"); });
                });
                #endregion
    
    
    
                Console.ReadKey();
            }
    
            /// <summary>
            /// 返回一个Task<int>
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            static Task<int> CreateTask(string name)
            {
                // 参数是Func<int>
                return new Task<int>(() => TaskMethodReturn(name));
            }
    
            static void TaskMethod(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                    name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            }
    
            static int TaskMethodReturn(string name)
            {
                Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                       name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
                Thread.Sleep(TimeSpan.FromSeconds(2));
                return 42;
            }
    
            /// <summary>
            /// 测试Task的线程来自于ThreadPool
            /// </summary>
            static void Test()
            {
                // 设置线程池中最大的线程数
                ThreadPool.SetMaxThreads(6, 6);
                // 创建Task的集合
                List<Task> taskList = new List<Task>();
                // 创建int类型的集合,用于存放线程ID
                List<int> threadIdList = new List<int>();
                // 使用Task循环创建50个线程
                for (int i = 0; i < 30; i++)
                {
                    int k = i;
                    Task task = Task.Run(() =>
                    {
                        // 当前线程ID加入到集合中
                        threadIdList.Add(Thread.CurrentThread.ManagedThreadId);
                        Console.WriteLine($"this is {k} 循环 ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                        // 休眠
                        Thread.Sleep(200);
                    });
                    // 把task加入到集合中
                    taskList.Add(task);
                }
    
                // 等待所有的线程执行完
                Task.WaitAll(taskList.ToArray());
                // 输出总数量
                Console.WriteLine($"线程总数:{threadIdList.Distinct().Count()}");
            }
    
            /// <summary>
            /// 模拟Coding过程
            /// </summary>
            /// <param name="name"></param>
            /// <param name="projectName"></param>
            static void CodingShow(string name, string projectName)
            {
                Console.WriteLine($"CodingShow Start  {name} {projectName}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
                long lResult = 0;
                for (int i = 0; i < 1_000_000_000; i++)
                {
                    lResult += i;
                }
    
                Console.WriteLine($"CodingShow   End  {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
            }
        }
    }
  • 相关阅读:
    1、TensorFlow简介
    4、numpy+pandas速查手册
    3、pandas
    2、Numpy常用函数
    11、C内存四区模型
    1、Numpy基础
    10、C++函数
    开始
    创建与删除SQL约束或字段约束
    Halcon
  • 原文地址:https://www.cnblogs.com/dotnet261010/p/12022290.html
Copyright © 2011-2022 走看看