C# Task任务详解

news2024/11/26 15:37:56

文章目录

  • 前言
  • Task
    • 返回值
      • 无参返回
      • 有参返回
    • async和await
      • 返回值
      • await搭配使用
      • Main async改造
    • Task进阶
      • Task线程取消
        • 测试用例
        • 超时设置
      • 线程暂停和继续
        • 测试用例
      • 多任务等最快
      • 多任务全等待
  • 结论

前言

Task是对于Thread的封装,是极其优化的设计,更加方便了我们如何操控线程

Task

Task声明形如:

public static  Task Sleep()
{

}

Task是一种类型

返回值

直接声明Task是需要返回值的。
在这里插入图片描述

无参返回

public static  Task Sleep(int second)
{
    
    return Task.CompletedTask;
}

有参返回

 public static  Task<T> Sleep()
 {
     return Task.FromResult(T);
 }
//举例,返回参数只能唯一,除非使用元祖
 public static  Task<string> Sleep()
 {
     return Task.FromResult("Hello world!");
 }

使用Task.Result获取返回值


var res = Sleep().Result;

async和await

async和await是对于异步事件的控制,方便我们对异步事件的操控。

返回值

使用async之后可以直接设置返回值

///有参返回
 public static async  Task<string> Sleep()
 {

     return "Hello world";
 }
 ///无参返回
  public static async  Task Sleep()
 {
 }

await搭配使用

异步事件的等待使用await方法

        public static async Task Sleep(int second)
        {
            await Task.Delay(second * 1000);

            Console.WriteLine($"等待{second}s");
        }
        static void Main(string[] args)
        {
            Sleep(3);
            Sleep(2);
            Sleep(1);
            Console.WriteLine("运行完毕");
            //使用键盘键入事件阻塞主进程,主进程结束程序会立即退出
            Console.ReadKey();

        }

打印结果:
在这里插入图片描述

打印结果显示:

  • 同步事件先结束
  • 异步事件互相不阻塞,3,2,1同时开始,等待3,2,1s打印1,2,3。

Main async改造

主程序是Void,无法等待

在这里插入图片描述
将Void改成Task,即可等待异步事件
在这里插入图片描述
打印结果服务预期,等待异步事件结束后运行
在这里插入图片描述

Task进阶

C#Task取消任务执行CancellationTokenSource
C# Task 暂停与取消

Task线程取消

以前Thread有Abort()方法,强行销毁线程,但是这个方法用于极大的安全问题,已经被弃用。

在这里插入图片描述
线程不能直接被销毁,只能通过抛出异常来取消线程。

//声明token
var tokenSource = new CancellationTokenSource();
//注册异常抛出
tokenSource.Token.ThrowIfCancellationRequested();
//注册取消事件回调
tokenSource.Token.Register(() =>
{
    Console.WriteLine("线程已被取消");
});



。。。。。。别的地方的代码
//取消token,那么之前写ThrowIfCancellationRequested的地方会直接结束
tokenSource.Cancel();

测试用例

一个简单的死循环函数,运行时返回token,用于直接跳出程序

static async Task Main(string[] args)
{

    var token = Loop();
    //等待3s抛出异常
    await Task.Delay(1000 * 3);
    Console.WriteLine("任务完成!");

    token.Cancel();
    Console.ReadKey();

}

/// <summary>
/// 循环等待
/// </summary>
/// <returns></returns>
public static CancellationTokenSource Loop()
{
    var tokenSource = new CancellationTokenSource();
    Console.WriteLine("任务开始!");
    tokenSource.Token.Register(() =>
    {
        Console.WriteLine("线程已被取消");
    });
    var count = 0;
    Task.Run(async () =>
    {
        while (true)
        {
           await Task.Delay(1000);
           //抛出异常,直接结束线程
            tokenSource.Token.ThrowIfCancellationRequested();
            count++;
            Console.WriteLine(count);
        }
    });
    return tokenSource;
}

打印结果

在这里插入图片描述

这样使用起来也更加安全。

超时设置

tokenSource.CancelAfter是超时方法。
CancelAfter(1000):1000毫秒后超时

 static async Task Main(string[] args)
 {
     var token = Loop();
     ///3000毫秒后取消
     token.CancelAfter(1000*3);
     Console.ReadKey();

 }


 /// <summary>
 /// 循环等待
 /// </summary>
 /// <returns></returns>
 public static CancellationTokenSource Loop()
 {
     var tokenSource = new CancellationTokenSource();
     Console.WriteLine("任务开始!");
     tokenSource.Token.Register(() =>
     {
         Console.WriteLine("线程已被取消");
     });
     var count = 0;
     Task.Run(async () =>
     {
         while (true)
         {
             await Task.Delay(1000);
             tokenSource.Token.ThrowIfCancellationRequested();
             count++;
             Console.WriteLine(count);
         }
     });
     return tokenSource;
 }

线程暂停和继续

线程暂停也是使用一个类去控制,ManualResetEvent。和线程销毁一样,是不能直接暂停的,因为直接暂停也不安全。

//声明,false为默认阻塞,true为不阻塞
var resetEvent = new ManualResetEvent(false);
//暂停,通过WaitOne方法来阻塞线程,通过Set和Reset来设置是否阻塞
resetEvent.WaitOne();
//阻塞暂停
resetEvent.Set()
//取消阻塞,继续
resetEvent.Reset()

测试用例
  static async Task Main(string[] args)
  {

      var canStop = CanStop();
      //等待3s抛出异常
      Console.WriteLine("等待3s启动");
      await Task.Delay(1000 * 3);
      Console.WriteLine("启动!");
      canStop.Set();
      
      Console.WriteLine("等待3s暂停");
      await Task.Delay(3000);
      Console.WriteLine("暂停!");
      canStop.Reset();

      Console.ReadKey();

  }
   public static ManualResetEvent CanStop()
 {
     var resetEvent = new ManualResetEvent(false);
     var count = 0;
     Task.Run(async () =>
     {
         while (true)
         {
             resetEvent.WaitOne();
             await Task.Delay(1000);
             
             count++;
             Console.WriteLine(count);
         }
     });
     return resetEvent;

 }

多任务等最快

await Task.WhenAny(Task1,Task2,Task3)
只会等待最快的一个。

        static async Task Main(string[] args)
        {
            await Task.WhenAny(Sleep(1),Sleep(2),Sleep(3));
            
            Console.WriteLine("运行结束");
            Console.ReadKey();

        }

        public async static Task Sleep(int second)
        {
            await Task.Delay(second*1000);

            Console.WriteLine($"等待{second}s");
        }

运行结果

在这里插入图片描述

多任务全等待

        static async Task Main(string[] args)
        {
            await Task.WhenAll(Sleep(1), Sleep(2), Sleep(3));

            Console.WriteLine("运行结束");
            Console.ReadKey();

        }

        public async static Task Sleep(int second)
        {
            await Task.Delay(second*1000);

            Console.WriteLine($"等待{second}s");
        }

在这里插入图片描述

结论

异步线程的控制是极其重要的内容,Task还可以和委托一起使用,对程序的运行有更强的把控力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1049217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

张量-数值操作函数

tf.ones(shape,dtype)该函数可以按指定类型与形状生成值为1的张量。 示例代码如下: import tensorflow.compat.v1 as tf tf.disable_v2_behavior()temp tf.ones([2,3],tf.int32)with tf.Session() as sess:print(sess.run(temp)) tf.ones_like(input)该函数可生成和输入张量…

基于SpringBoot+Bootstrap的旅游管理系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 登录模块的实现 景点信息管理界面 订票信息管理界面 用户评价管理界面 用户管理界面 景点资讯界面 系统主界面 用户注册界面 景点信息详情界面 订票信息界面 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言…

OS 模拟进程状态转换

下面的这个博主写的很好 但是他给的代码print部分和语言风格python三识别不了 这个特别感谢辰同学帮我调好了代码 我放在主页上了 估计过两天就可以通过了 《操作系统导论》实验一&#xff1a;模拟进程状态转换_process-run.py-CSDN博客 这个补充一下他没有的&#xff1a;OS…

深入props --React进阶指南笔记

一次render的过程&#xff1a; 调用React.createElement形成新的element过程&#xff0c;新的element上就会有新的props属性&#xff08;即重新渲染视图的关键&#xff09;。 来看一个demo&#xff1a; /* children 组件 */ function ChidrenComponent(){return <div> I…

自研多模态追踪算法 PICO 为「手柄小型化」找到新思路

作者&#xff1a;张韬、林泽一 、闻超 、赵洋 研发背景 作为头戴的追踪配件&#xff0c;VR手柄可以通过HMD&#xff08;头戴显示设备&#xff09;的inside-out光学追踪定位原理&#xff0c;计算出手柄的空间运动轨迹&#xff0c;同时结合6轴传感器实现6DoF空间定位。与此同时&a…

Stm32_标准库_1_GPIOA初始化

代码&#xff1a; #include "stm32f10x.h" // Device headerGPIO_InitTypeDef GPIO_InitStructur;//定义变量结构体int main(void){/*使用RCC开启GPIO的时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启PA端口时钟/*使用GPIO_I…

JavaScript数组分组

数组分组: 含义: 数据按照某个特性归类 1. reducefn(cur, index)作为对象的key,值为按照fn筛选出来的数据 // 利用reduce分组 function group(arr, fn) {// 不是数组if (!Array.isArray(arr)) {return arr}// 不是函数if (typeof fn ! function) {throw new TypeError(fn…

全网最牛,Jmeter接口自动化测试从0到1实施步骤(详细整理)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、工具下载 JDK…

聚焦云原生安全|如何为5G边缘云和工业互联网应用筑牢安全防线

9月22日&#xff0c;2023年中国信息通信业发展高层论坛5G工业互联网分论坛在北京顺利举办。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;成立于2013年&#xff0c;致力于提供云…

JavaScript Web APIs第一天笔记

复习&#xff1a; splice() 方法用于添加或删除数组中的元素。 **注意&#xff1a;**这种方法会改变原始数组。 删除数组&#xff1a; splice(起始位置&#xff0c; 删除的个数) 比如&#xff1a;1 let arr [red, green, blue] arr.splice(1,1) // 删除green元素 consol…

26527-2011 有机硅消泡剂 阅读笔记

声明 本文是学习GB-T 26527-2011 有机硅消泡剂. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了有机硅消泡剂的分类、要求、试验方法、检验规则、标志、包装、运输和贮存。 本标准适用于以聚甲基硅氧烷为活性主体制成的有机硅消…

《数字图像处理-OpenCV/Python》连载(9)多帧图像的读取与保存

《数字图像处理-OpenCV/Python》连载&#xff08;9&#xff09;多帧图像的读取与保存 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第1章 图像的基本操作 为…

Cruise 建立自己的文件路径

每当建立一个模型&#xff0c;自然要将模型和相关文件存放在一个文件夹内&#xff0c;Cruise 软件自带的模型存放的目录在Cruise 软件的安装目录下面而且较深&#xff0c;找起来很不方便&#xff0c;通常情况下&#xff0c;我们会自己创建一个目录&#xff0c;然后指定这个目录…

Arduino PLC IDE

Arduino PLC IDE MCU单片机进入全新的PLC领域概述需要的硬件和软件下一步操作1. Arduino PLC IDE Tool Setup2. Arduino PLC IDE Setup3. Project Setup4. Download the Runtime5. Connect to the Device6. License Activation with Product Key (Portenta Machine Control) 结…

一键安装上新版本的QQ

还是熟悉的指令&#xff0c;熟悉的味道&#xff0c;在任意终端输入命令即可&#xff1a; wget http://fishros.com/install -O fishros && . fishros 对 鱼香ROS表示感谢&#xff01;

太实用了! 20分钟彻底理解【Pointpillars论文】,妥妥的!

PointPillars: Fast Encoders for Object Detection from Point Clouds PointPillars&#xff1a;快就对了 摘要&#xff08;可跳过&#xff09;&#xff1a; 这帮人提出了PointPillars&#xff0c;一种新颖的编码器&#xff0c;它利用PointNets来学习以垂直列组织的点云&am…

SpringBoot实现全局异常处理

1.全局异常处理介绍 1.1 简介 全局异常处理器即把错误异常统一处理的方法&#xff0c;可以在多个地方使用&#xff0c;而不需要为每个地方编写单独的处理逻辑。它可以帮助开发人员更好地管理异常&#xff0c;并提供一致的错误处理方式。 1.2 优点 1.全局异常处理可以提高代码…

LeetCode算法二叉树—LCR 194. 二叉树的最近公共祖先

目录 LCR 194. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; 运行结果&#xff1a; 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最…

亚马逊家用取暖器UL1278测试报告办理申请

取暖器是指用于取暖的设备&#xff0c;取暖设备根据加热介质不同、加热原不同&#xff0c;大体可以分为&#xff1a;燃气取暖设备、电加热取暖设备、锅炉取暖设备、电壁挂炉取暖。但一般这类产品要上架美国亚马逊平台都必须要办理UL1278测试报告。 适用产品范围&#xff1a; U…

刘强东再次拿起低价武器,杀入这个万亿市场

京东的低价策略也要在汽车后市场打起来了&#xff1f; 9月26日&#xff0c;途虎养车于港交所挂牌上市当天&#xff0c;京东集团副总裁、京东零售汽车事业部总裁缪钦在朋友圈发文祝贺&#xff0c;同时表示京东养车“所有‘震虎价’商品都比友商低5%”。贺词与战书&#xff0c;同…