文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何在C#项目中使用Task实现并行和多线程编程

2023-06-06 11:40

关注

这期内容当中小编将会给大家带来有关如何在C#项目中使用Task实现并行和多线程编程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

任务和线程的区别:

任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。

任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。

 一、认识Task和Task的基本使用

1、认识Task

首先来看一下Task的继承结构。Task标识一个异步操作。

如何在C#项目中使用Task实现并行和多线程编程

可以看到Task和Thread一样,位于System.Threading命名空间下,这也就是说他们直接有密不可分的联系。下面我们来仔细看一下吧!

2、创建Task

创建Task的方法有两种,一种是直接创建——new一个出来,一种是通过工厂创建。下面来看一下这两种创建方法:

//第一种创建方式,直接实例化     var task1 = new Task(() =>     {      //TODO you code     });

这是最简单的创建方法,可以看到其构造函数是一个Action,其构造函数有如下几种,比较常用的是前两种。

如何在C#项目中使用Task实现并行和多线程编程

//第二种创建方式,工厂创建     var task2 = Task.Factory.StartNew(() =>     {      //TODO you code     });

这种方式通过静态工厂,创建以个Task并运行。下面我们来建一个控制台项目,演示一下,代码如下:

要添加System.Threading.Tasks命名控件引用。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace TaskDemo{  class Program  {   static void Main(string[] args)   {     var task1 = new Task(() =>     {      Console.WriteLine("Hello,task");     });     task1.Start();     var task2 = Task.Factory.StartNew(() =>     {      Console.WriteLine("Hello,task started by task factory");     });     Console.Read();   }  }}

这里我分别用两种方式创建两个task,并让他们运行。可以看到通过构造函数创建的task,必须手动Start,而通过工厂创建的Task直接就启动了。

下面我们来看一下Task的声明周期,编写如下代码:

var task1 = new Task(() =>     {      Console.WriteLine("Begin");      System.Threading.Thread.Sleep(2000);      Console.WriteLine("Finish");     });     Console.WriteLine("Before start:" + task1.Status);     task1.Start();     Console.WriteLine("After start:" + task1.Status);     task1.Wait();     Console.WriteLine("After Finish:" + task1.Status);     Console.Read();

  task1.Status就是输出task的当前状态,其输出结果如下:

如何在C#项目中使用Task实现并行和多线程编程

可以看到调用Start前的状态是Created,然后等待分配线程去执行,到最后执行完成。

从我们可以得出Task的简略生命周期:

Created:表示默认初始化任务,但是“工厂创建的”实例直接跳过。

WaitingToRun: 这种状态表示等待任务调度器分配线程给任务执行。

RanToCompletion:任务执行完毕。

 二、Task的任务控制

  Task最吸引人的地方就是他的任务控制了,你可以很好的控制task的执行顺序,让多个task有序的工作。下面来详细说一下:

1、Task.Wait

在上个例子中,我们已经使用过了,task1.Wait();就是等待任务执行完成,我们可以看到最后task1的状态变为Completed。

2、Task.WaitAll

看字面意思就知道,就是等待所有的任务都执行完成,下面我们来写一段代码演示一下:

static void Main(string[] args)   {     var task1 = new Task(() =>     {      Console.WriteLine("Task 1 Begin");      System.Threading.Thread.Sleep(2000);      Console.WriteLine("Task 1 Finish");     });     var task2 = new Task(() =>     {      Console.WriteLine("Task 2 Begin");      System.Threading.Thread.Sleep(3000);      Console.WriteLine("Task 2 Finish");     });          task1.Start();     task2.Start();     Task.WaitAll(task1, task2);     Console.WriteLine("All task finished!");     Console.Read();   }

其输出结果如下:

如何在C#项目中使用Task实现并行和多线程编程

可以看到,任务一和任务二都完成以后,才输出All task finished!

3、Task.WaitAny

这个用发同Task.WaitAll,就是等待任何一个任务完成就继续向下执行,将上面的代码WaitAll替换为WaitAny,输出结果如下:

如何在C#项目中使用Task实现并行和多线程编程

4、Task.ContinueWith

就是在第一个Task完成后自动启动下一个Task,实现Task的延续,下面我们来看下他的用法,编写如下代码:

static void Main(string[] args)   {     var task1 = new Task(() =>     {      Console.WriteLine("Task 1 Begin");      System.Threading.Thread.Sleep(2000);      Console.WriteLine("Task 1 Finish");     });     var task2 = new Task(() =>     {      Console.WriteLine("Task 2 Begin");      System.Threading.Thread.Sleep(3000);      Console.WriteLine("Task 2 Finish");     });          task1.Start();     task2.Start();     var result = task1.ContinueWith<string>(task =>     {      Console.WriteLine("task1 finished!");      return "This is task result!";     });     Console.WriteLine(result.Result.ToString());     Console.Read();   }

执行结果如下:

如何在C#项目中使用Task实现并行和多线程编程

可以看到,task1完成之后,开始执行后面的内容,并且这里我们取得task的返回值。

在每次调用ContinueWith方法时,每次会把上次Task的引用传入进来,以便检测上次Task的状态,比如我们可以使用上次Task的Result属性来获取返回值。我们还可以这么写:

var SendFeedBackTask = Task.Factory.StartNew(() => { Console.WriteLine("Get some Data!"); })              .ContinueWith<bool>(s => { return true; })              .ContinueWith<string>(r =>                {                 if (r.Result)                 {                  return "Finished";                 }                 else                 {                  return "Error";                 }               });     Console.WriteLine(SendFeedBackTask.Result);

首先输出Get some data,然后执行第二个获得返回值true,最后根据判断返回Finished或error。输出结果:

Get some Data!

Finished

其实上面的写法简化一下,可以这样写:

Task.Factory.StartNew<string>(() => {return "One";}).ContinueWith(ss => { Console.WriteLine(ss.Result);});

输出One,这个可以看明白了吧~

 更多ContinueWith用法参见:http://technet.microsoft.com/zh-CN/library/dd321405

5、Task的取消

前面说了那么多Task的用法,下面来说下Task的取消,比如我们启动了一个task,出现异常或者用户点击取消等等,我们可以取消这个任务。

如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话就return或者抛出异常,抛出异常后面再说,因为还没有说异常处理的东西。

下面在代码中看下如何实现任务的取消,代码如下:

var tokenSource = new CancellationTokenSource();     var token = tokenSource.Token;     var task = Task.Factory.StartNew(() =>     {      for (var i = 0; i < 1000; i++)      {        System.Threading.Thread.Sleep(1000);        if (token.IsCancellationRequested)        {         Console.WriteLine("Abort mission success!");         return;        }      }     }, token);     token.Register(() =>     {      Console.WriteLine("Canceled");     });     Console.WriteLine("Press enter to cancel task...");     Console.ReadKey();     tokenSource.Cancel();     Console.ReadKey();//这句忘了加,程序退出了,看不到“Abort mission success!“这个提示

这里开启了一个Task,并给token注册了一个方法,输出一条信息,然后执行ReadKey开始等待用户输入,用户点击回车后,执行tokenSource.Cancel方法,取消任务。其输出结果如下:

如何在C#项目中使用Task实现并行和多线程编程

上述就是小编为大家分享的如何在C#项目中使用Task实现并行和多线程编程了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯