一、相关介绍
.NetFramework3.0时代实现,C#中多线程、异步编程最佳实践,特点:
1、所有的Task操作的线程来自线程池,避免了频繁的线程创建及销毁
2、含有丰富的Api,能满足我们在开发过程中的各种场景(异步、多线程的执行顺序控制)
Task的执行底层还是thread执行
 
二、Task的创建方式
1、Task.Start
            //1、start——无返回值的方法,无参数(Action)、有一个参数Action<object?>
//1.1带参数的——public Task(Action<object?> action, object? state);
Action<Object?> action = objects =>
{
NoReturn(objects?.ToString());
};
var task1 = new Task(action, new Person());
task1.Start();
////1.2不带参数的——public Task(Action action);
Action action1 = NoParameterNoReturn;
var task2 = new Task(action1);
task2.Start();

2、Task.Run

相关重载

//public static Task Run(Action action, CancellationToken cancellationToken);
//public static Task<TResult> Run<TResult>(Func<TResult> function);
//Task<string>.Run(NoParameterReturn);
//public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken);
//public static Task Run(Func<Task?> function);暂时没确定应用场景

public static class TaskRunSummary
{
public static async void RunTaskSummary()
{
//Task.Run() Action Lambda
Task t1 = Task.Run(() => { Debug.WriteLine("Task.Run() Action Lambda"); });
await t1; //Task.Run() Func<Task> Lambda Async
Task t2 = Task.Run(async () => { Debug.WriteLine("Task.Run() Func<Task> Lambda Async"); });
await t2; //Task.Run() Func<Task> Method Async
Task t3 = Task.Run(MethodAsync);
await t3; //Task.Run<TResult>() Func<TResult> Lambda
Task<string> t4 = Task.Run<string>(() => { Debug.WriteLine("Task.Run<TResult>() Func<TResult> Lambda"); return "Task.Run<TResult>() Func<TResult> Lambda Return Value"; });
Console.WriteLine(await t4); //Task.Run<TResult>() Func<Task<TResult>> Lambda Async
Task<string> t5 = Task.Run<string>(async () => { Debug.WriteLine("Task.Run<TResult>() Func<Task<TResult>> Lambda Async"); return "Task.Run<TResult>() Func<Task<TResult>> Lambda Async Return Value"; });
Console.WriteLine(await t5); //Task.Run<TResult>() Func<Task<TResult>> Method Async
Task<string> t6 = Task.Run<string>(new Func<Task<string>>(ParameteredMethodAsync));
Console.WriteLine(await t6);
} public static async Task MethodAsync()
{
Debug.WriteLine("Task.Run() Func<Task> Method Async");
} public static async Task<string> ParameteredMethodAsync()
{
Debug.WriteLine("Task.Run<TResult>() Func<Task<TResult>> Method Async");
return "Task.Run<TResult>() Func<Task<TResult>> Method Async Return Value";
}
}

3、Task.Factory.StartNew——支持Action、Action<T>、Func<T>等参数

            Task.Factory.StartNew(NoParameterNoReturn);
//3.1TaskFactory执行,和3差不多3是创建一个匿名TaskFactory去执行
TaskFactory taskFactory1 = new TaskFactory();
taskFactory1.StartNew(NoParameterNoReturn);
public static void NoParameterNoReturn()
{ Debug.WriteLine("无参数无返回值方法");
}

三、Task的相关属性及方法

Task.Delay

1.Task.Delay实质是创建一个任务,再任务中开启一个定时间,然后延时指定的时间
2.Task.Delay不和await一起使用情况,当代码遇到Task.Delay一句时,创建了了一个新的任务去执行延时去了,当前代码继续往下执行
3.Task.Delay和await一起使用,当代码遇到await Task.Delay时候,当前线程要等该行代码执行完成后,再继续执行后面的代码

Delay与Thread.sleep的区别

Thread.Sleep——这是暂停执行的经典方式。此方法将暂停当前线程,直到经过给定的时间,在此期间当前线程无响应

Task.Delay——任务延迟的作用方式与线程截然不同。延迟将创建一个任务,该任务将在延迟一段时间后完成。任务延迟不会阻塞调用线程,因此调用线程将保持响应。

ContinueWith——

ContinueWith(Action<Task>)创建一个在目标 Task 完成时异步执行的延续任务。常和Task.Delay一起使用用来做延迟动作

        public static async Task UseDelayWithAwait()
{
Debug.WriteLine($"使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行开始》》");
Stopwatch sw = Stopwatch.StartNew();
await Task.Delay(1000);
sw.Stop();
Debug.WriteLine($"使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行完毕,耗时{sw.ElapsedMilliseconds}毫秒");
}
public static void UseDelayWithNoAwait()
{
Debug.WriteLine($"不使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行开始》》");
Stopwatch sw = Stopwatch.StartNew();
Task.Delay(1000);
sw.Stop();
Debug.WriteLine($"不使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行完毕,耗时{sw.ElapsedMilliseconds}毫秒");
}
public static async Task ContinueWithMethod()
{
Stopwatch sw = Stopwatch.StartNew();
Debug.WriteLine($"当前线程id:{Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(3000).ContinueWith(t =>
{
Debug.WriteLine($"ContinueWith创建的Task线程id:{Thread.CurrentThread.ManagedThreadId}");
});
sw.Stop();
Debug.WriteLine($"延迟三秒后的Task执行完毕,耗时{sw.ElapsedMilliseconds}毫秒");
}

//执行结果

            //Task.Delay总结
{
//1、当前cpu执行线程遇到await Task.Delay时,会等待但他等待时会执行其他任务(不阻塞),在等待完成时由本执行cpu或其他执行cpu继续执行,所以await delay前后的代码可能不是一个cpu执行线程在执行,所以会出现下面的结果
Task.Run(() => TaskDelaySummary.UseDelayWithAwait());
//结果打印1:
//使用Await的线程id:4执行开始》》
//使用Await的线程id:5执行完毕,耗时1011毫秒
//结果打印2:
//使用Await的线程id:7执行开始》》
//使用Await的线程id:7执行完毕,耗时1007毫秒 //2、在不和await调用时,当执行cpu遇到Task.Delay时,不会等待,直接继续执行,所以前后的执行线程id是一致的
Task.Run(() => TaskDelaySummary.UseDelayWithNoAwait());
//结果打印:
//不使用Await的线程id:4执行开始》》
//不使用Await的线程id:4执行完毕,耗时0毫秒

Task.Run(async () =>
{
await TaskContinueWithSummary.ContinueWithMethod();
});
//结果打印:
//当前线程id:4
//ContinueWith创建的Task线程id:5
//延迟三秒后的Task执行完毕,耗时3015毫秒 }

C# 线程(四)——Task初始的更多相关文章

  1. 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq

    常量,字段,构造方法   常量 1.什么是常量 ​ 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...

  2. C#中的线程四(System.Threading.Thread)

    C#中的线程四(System.Threading.Thread) 1.最简单的多线程调用 System.Threading.Thread类构造方法接受一个ThreadStart委托,改委托不带参数,无 ...

  3. 第四章初始CSS3预习笔记

    第四章 初始CSS3预习笔记 一: 1: 什么是CSS? 全称是层叠样式表;/通常又称为风格样式表,.他是用来进行网页风格设计的; 2:CSS的优势: 1>内容以表现分离,即使用u前面学习的HT ...

  4. 菜鸟之旅——学习线程(Task)

    前面两篇回顾线程和线程池的使用方法,微软在.NET4.5推出了新的线程模型-Task.本篇将简单的介绍Task的使用方法. Task与线程 Task与线程或者说线程池关系紧密,可以说是基于线程池实现的 ...

  5. C#线程篇---Task(任务)和线程池不得不说的秘密(5)

    在上篇最后一个例子之后,我们发现了怎么去使用线程池,调用ThreadPool的QueueUserWorkItem方法来发起一次异步的.计算限制的操作,例子很简单,不是吗? 然而,在今天这篇博客中,我们 ...

  6. C#线程篇---Task(任务)和线程池不得不说的秘密

    我们要知道的是,QueueUserWorkItem这个技术存在许多限制.其中最大的问题是没有一个内建的机制让你知道操作在什么时候完成,也没有一个机制在操作完成是获得一个返回值,这些问题使得我们都不敢启 ...

  7. java线程四种状态

    一个线程可以有四种状态: 1.新(new), 即线程刚刚创建,而并未执行 2.可运行(runnable),意味着一旦时间分片机制有空闲的CPU周期提供给一个线程,那个线程便可立即开始运行.因此,线程可 ...

  8. 线程 线程池 Task

    首先声明 这是读了 愉悦的绅士 文章 <菜鸟之旅——学习线程(线程和线程池)> <Task与线程> 的一些个人总结,还是那句话,如有不对,欢迎指正 文章以代码加注释的方法展示. ...

  9. spring boot tomcat 线程数 修改初始线程数 统计性能 每百次请求耗时

    [root@f java]# tail -30 nohup.outsearchES-TimeMillisSpent:448P->1602@fT->http-nio-8080-exec-3t ...

  10. Linux 进程与线程四(加锁--解锁)

    线程共享进程的内存空间,打开的文件描述符,全局变量. 当有多个线程同事访问一块内存空间或者一个变量.一个文件描述符,如果不加控制,那么可能会出现意想不到的结果. 原子操作 对于我们的高级语言(C语言, ...

随机推荐

  1. Ceph PG状态介绍

    本文分享自天翼云开发者社区<Ceph PG状态介绍>,作者:wwwdl 一.基本概念 size:副本数(如三副本,size=3): min_size:支持可读写的最小副本数(如三副本,mi ...

  2. 如何让领导轻松在本地查看Allure报告

    如何让领导轻松在本地查看Allure报告 问题描述 当我们把精心生成的Allure报告原始文件发送给领导后,领导直接打开index.html文件时,页面却一直处于加载状态,无法显示数据. 通过F12开 ...

  3. Calcite 获取jdbc连接流程

    一.类调用 简介:calcite可以连接各数据源,做查询.可以收口查询权限,查询多引擎需求 二. 获取Connection发送的请求 请求介绍文档:https://calcite.apache.org ...

  4. Luogu P4588 数学运算 题解 [ 绿 ] [ 线段树 ]

    Luogu P4588 数学运算. 虽然是一个很典的题,但里面的思想还是比较值得记录的. 假做法 一开始看到此题还以为是乘法逆元的模板题,但看到 \(m\) 与 \(M\) 不互质,就知道这种做法是假 ...

  5. 一种将历史地图坐标配准到GIS中的方法

    经常我们看到历史地图影像,比如谭图里面的各个历史朝代的大地图, 然后我们希望利用这个影像作为图层或者叫底图,然后在GIS软件上编辑一些矢量文件, 从而产生的地图矢量文件具有真实的经纬度坐标,不是单单的 ...

  6. 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~

    大家好,我是汤师爷! 最近,腾讯发布了一款ima产品,主打用AI来帮你搜索信息.管理知识库. 说实话,一开始用混元大模型,感觉不咋地,很鸡肋的. 不过最近腾讯把DeepSeek R1接进来了,一下子解 ...

  7. Android应用借助LinearLayout实现垂直水平居中布局

    首先说的是LinearLayout布局下的居中一般是这样的: (注意:android:layout_width="fill_parent" android:layout_heigh ...

  8. Typescript通用帮助类,格式化日期时间等

    /** * 格式化日期选项 */ export class DateFormatOption { "M+": number;//月 "d+": number;/ ...

  9. Typecho博客服务器搬家换空间方法教程

    Typecho 博客搬家方法步骤: 1.备份Typecho博客数据库,进入到phpmyadmin选择自己博客的数据表进行导出备份 2.使用FTP(或者登陆空间控制面板)把所有的Typecho文件下载到 ...

  10. dx12学习之旅-

    记录一下,第一篇博客2024年7月26日下午. 计划在毕业后从事游戏开发的工作,现在在学习龙书dx12,平时会写一些对龙书内容上的一些理解.在读完全书之后,会考虑进行一次龙书相关的总结,不过这应该要很 ...