服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#多线程编程Task用法详解

C#多线程编程Task用法详解

2023-02-22 16:40.NET开发菜鸟 C#

本文详细讲解了C#多线程编程Task的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、基本概念

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}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
          });
          Console.WriteLine("启动");
          Console.ReadKey();
      }
  }
}

 

二、Task用法

创建任务

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

1、使用Task创建无返回值

先看一下Task的定义:

C#多线程编程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);
      }
  }
}

程序运行结果:

C#多线程编程Task用法详解

注:任务的状态,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);
      }
  }
}

程序运行结果:

C#多线程编程Task用法详解

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);
      }
  }
}

程序运行结果:

C#多线程编程Task用法详解

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;
      }
  }
}

程序运行结果:

C#多线程编程Task用法详解

我们在文章开始的时候说过,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()}");
}

程序运行结果:

C#多线程编程Task用法详解

从结果中可以看出,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")} ");
      }
  }
}

程序运行结果:

C#多线程编程Task用法详解

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

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

程序运行结果:

C#多线程编程Task用法详解

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

1、WaitAll()

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

C#多线程编程Task用法详解

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("所有模块都开发完成,开始搭建测试环境");

程序运行结果:

C#多线程编程Task用法详解

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

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

2、WaitAny()

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

C#多线程编程Task用法详解

修改后的代码如下:

// 定义一个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("有模块开发完成,开始搭建测试环境");

程序运行结果:

C#多线程编程Task用法详解

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

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("所有模块开发完成"));

程序运行结果:

C#多线程编程Task用法详解

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("某一个模块开发完成"));

程序运行结果:

C#多线程编程Task用法详解

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

5、ContinueWith

ContinueWith表示回调,代码如下:

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

程序执行结果:

C#多线程编程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.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")} ");
      }
  }
}

到此这篇关于C#多线程编程Task用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/dotnet261010/p/12022290.html

延伸 · 阅读

精彩推荐
  • C#WCF实现的计算器功能实例

    WCF实现的计算器功能实例

    这篇文章主要介绍了WCF实现的计算器功能,结合具体实例形式较为详细的分析了WCF实现计算器功能的具体步骤与相关操作技巧,需要的朋友可以参考下...

    傻丫头与科技10652022-01-10
  • C#OpenXml读取word内容的实例

    OpenXml读取word内容的实例

    下面小编就为大家分享一篇OpenXml读取word内容的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    *飞*7832022-02-16
  • C#C#实现泛型List分组输出元素的方法

    C#实现泛型List分组输出元素的方法

    这篇文章主要介绍了C#实现泛型List分组输出元素的方法,涉及C#针对List的遍历、排序、输出等相关操作技巧,需要的朋友可以参考下...

    SharpL7152022-02-13
  • C#c#基础——了解程序结构

    c#基础——了解程序结构

    这篇文章主要介绍了c# 程序结构的相关资料,文中讲解非常细致,帮助大家更好的理解和学习C#,感兴趣的朋友可以了解下...

    菜鸟教程3582022-09-24
  • C#详解C#中 Thread,Task,Async/Await,IAsyncResult的那些事儿

    详解C#中 Thread,Task,Async/Await,IAsyncResult的那些事儿

    本文主要介绍了C#中 Thread,Task,Async/Await,IAsyncResult的相关知识。具有一定的参考价值,下面跟着小编一起来看下吧...

    Mr靖5792021-12-20
  • C#深入分析C# 线程同步

    深入分析C# 线程同步

    这篇文章主要介绍了C# 线程同步的的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    JoeSnail3462022-09-15
  • C#C#处理Access中事务的方法

    C#处理Access中事务的方法

    这篇文章主要介绍了C#处理Access中事务的方法,涉及C#中事物的实现及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    baggio709558611802021-10-29
  • C#C# 压榨cpu的办法(推荐)

    C# 压榨cpu的办法(推荐)

    这篇文章主要介绍了C# 压榨cpu的办法,通过修改num的值,观察cpu的核数,例如我电脑是8核的,改成8,运行时各个核都能跑满,感兴趣的朋友跟随小编一起看...

    飞起来的帅哥8932022-12-14