多线程-Task、await/async
Task创建无返回值
Task是.netframwork4.0重新分装的多线程类。原因以前的多线程(thread threadpool)不好用。(.net framwork也是的发展的,现在的EF,刚开始是一个edmx文件,现在的code first,ef轻量级。但是其他有的技术也是死掉了)
Task具有线程执行的可控性,返回值,代码书写简单,性能好等特点。
Task创建主要有三种方式
1、Task参数
Task t = new Task(() => {for (int i = 0; i < 10; i++){Console.WriteLine(i);} }); t.Start();
View Code
Action,Action<object>,object state,CancellationToken,TaskCreationOptions
Action<object>:task创建有参数的任务,参数只能是object
object:带有参数委托的参数。
CancellationToken:线程取消通知
TaskCreationOptions:控制Task的执行方式
// // 摘要: // 指定可控制任务的创建和执行的可选行为的标志。 [Flags] public enum TaskCreationOptions {//// 摘要:// 指定应使用默认行为。None = 0,//// 摘要:// 提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。PreferFairness = 1,//// 摘要:// 指定任务将是长时间运行的、粗粒度的操作,涉及比细化的系统更少、更大的组件。它会向 System.Threading.Tasks.TaskScheduler// 提示,过度订阅可能是合理的。您可以通过过度订阅创建比可用硬件线程数更多的线程。LongRunning = 2,//// 摘要:// 指定将任务附加到任务层次结构中的某个父级。有关详细信息,请参阅 已附加和已分离的子任务。AttachedToParent = 4,//// 摘要:// 如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发。DenyChildAttach = 8,//// 摘要:// 防止环境计划程序被视为已创建任务的当前计划程序。这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 System.Threading.Tasks.TaskScheduler.Default// 当前计划程序。HideScheduler = 16 }
View Code
2、Task.Factory.StartNew
Action,Action<object>,object state,CancellationToken,TaskCreationOptions,TaskScheduler
TaskScheduler:定义:用于计划所创建的 System.Threading.Tasks.Task 的 System.Threading.Tasks.TaskScheduler。(并看不出来是什么意思,英文意思 任务调度器)
返回值是一个Task
Task.Factory.StartNew(() => {for (int i = 10; i < 20; i++){Console.WriteLine(i);} });
View Code
3、TaskFactory
Task.Factory是TaskFactory的一个实例。
TaskFactory tf = new TaskFactory(); tf.StartNew(() => {for (int i = 20; i < 30; i++){Console.WriteLine(i);} });
View Code
上面的都是不带返回参数的任务
Task创建有返回值
一般项目中的返回类型都会特定的封装一个通用的类型。所有都会有返回值。
Task<string> t = new Task<string>(GetName); t.Start(); Console.WriteLine(t.Result); Console.WriteLine("结束");
View Code
public static string GetName() {for (int i = 0; i < 10; i++){Console.WriteLine(i);}return "臧峰"; }
View Code
注意在获取返回值的时候,t.Result会卡着线程,一只等待线程返回结果。
Task等待
1、为什么要等待呢,因为线程大部分都要计算已给结果,所以我们要等待这个结果。
2、public void Wait(。。。。);
位于Task类中(实例方法。另外还有几个静态方法)。
定义:等待 System.Threading.Tasks.Task 完成执行过程(卡着其他线程)。
参数可以设置等待时间,CancellationToken(任务取消) 等待期间可以取消任务。
3、public static void WaitAll(params Task[] tasks....);
定义:等待提供的所有 System.Threading.Tasks.Task 对象完成执行过程。(就是当前线程要等这个参数列表中线程全部执行完后 才执行。注意:waitall前面其他的子线程还是在继续执行)
参数:等待任务列表,事件,CancellationToken
4、public static int WaitAny(params Task[] tasks);
定义:等待提供的任一 System.Threading.Tasks.Task 对象完成执行过程。
参数:等待任务列表,事件,CancellationToken
5、Task的属性方法
AsyncState | 就是当任务核心方法带参数的时候,参数值 |
Status | 任务执行进度的状态 |
CreationOptions | 任务创建和执行的行为 |
Id | 任务线程ID |
IsCanceled | 任务是否被取消 |
IsCompleted | 任务是否完成 |
IsFaulted | 任务是否失败 |
Result | 任务返回值,该值只适用于有返回参数的任务 |
ContinueWith() | 线程执行完之后执行另外一个任务 |
GetAwaiter() | 获取等待这个线程的等待着 |
Start() | 发起一个任务 |
Wait() | 当前调用wait的任务线程等待 |
这些是常用的
Task回调
//------------------------Task回调------------------------- Task<int> t = new Task<int>(() => {var temp = 0;for (int i = 0; i < 10; i++){temp += i;}return temp; });t.ContinueWith<string>((f) => {Console.WriteLine(f.Result.ToString());return f.Result.ToString(); }); t.Start();//------------------TaskFactory回调---------------------------- TaskFactory<int> tf = new TaskFactory<int>(); var tft = tf.StartNew(() =>{var temp = 0;for (int i = 0; i < 10; i++){temp += i;}return temp;}); tft.ContinueWith<string>((f) => {Console.WriteLine(f.Result.ToString());return f.Result.ToString(); });//-----------------------ContinueWhenAll-------------------------- var cts = new CancellationTokenSource(); TaskFactory<int> tf1 = new TaskFactory<int>(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);Task<int> t1 = tf1.StartNew(() => { Console.WriteLine(1); return 1; }); Task<int> t2 = tf1.StartNew(() => { Console.WriteLine(2); return 2; }); Task<int> t3 = tf1.StartNew(() => { Console.WriteLine(3); return 3; }); Task<int> t4 = tf1.StartNew(() => { Console.WriteLine(4); return 4; }); Task<int> t5 = tf1.StartNew(() => { Console.WriteLine(5); return 5; });//意思就是说当这些所有的线程都执行完了,在执行后面的线程 //第一个参数就是要执行的线程数组 //第二个参数就是 继续执行的线程 var tcwa = tf1.ContinueWhenAll(new[] { t1, t2, t3, t4, t5 }, tlReturn =>{int temp = 0;for (int i = 0; i < tlReturn.Length; i++){temp += tlReturn[i].Result;}Console.WriteLine(temp);return temp;});var tft1 = tf1.StartNew(() => {var temp = 0;for (int i = 0; i < 10; i++){temp += i;}Console.WriteLine(temp);return temp; });//-------------------------FromAsync----------------------------------- TaskFactory<long> tfFA = new TaskFactory<long>(); Func<long> faDel = (() => {Console.WriteLine("臧锋");return 10; }); tfFA.FromAsync(faDel.BeginInvoke(null, null), (tr) => {Console.WriteLine(tr.IsCompleted);return 11; });
View Code
还是先了解一下TaskFactory
ContinueWhen不会卡当前线程。wait会卡当前线程。
CancellationToken | 任务取消标记 |
ContinuationOptions | 字面意思 任务延续选择。官方注释不敢恭维。和ContinueWhenAll、ContinueWhenAny有关 |
CreationOptions | 指定此任务工厂的默认创建选项。(任务执行顺序,是否长时间执行...) |
Scheduler | 任务工厂的任务计划程序。表示一个处理将任务排队到线程中的低级工作的对象。 |
ContinueWhenAll |
创建一个延续任务,它将在提供的组中的所有任务完成后马上开始。第一个参数P1:线程列表,就是要执行的线程 (必须有调用ContinueWhenAll的TaskFactory创建) 第二个参数P2:回调函数 (回调函数的第一个参数为第一个参数P1,回调函数第二个参数为返回值,由TaskFactory<>定义的)。 执行顺序 P1先执行,然后P2执行。 TaskFactory的任务为随机执行 |
ContinueWhenAny | 创建一个延续任务,它将在提供的组中的任何任务完成后马上开始。 |
FromAsync |
创建一个任务,它在指定的 System.IAsyncResult 完成时执行一个结束方法函数。(官方解释有点绕 其实就是 通过它可以把一个异步的任务转换为一个Task,返回值是一个Task,最后在执行一个回调函数) 吐槽一下,官方的翻译是不是都是电脑翻译的。 |
StartNew | 创建开启任务 |
Task取消
主要是类CancellationTokenSource
定义:通知 System.Threading.CancellationToken,告知其应被取消。
可以马上取消,还可以设置时间取消。
CancellationTokenSource clt = new CancellationTokenSource(); TaskFactory tf = new TaskFactory(clt.Token); tf.StartNew(() => {int temp = 0;for (int i = 0; i < 10000; i++){Thread.Sleep(10);if (!clt.IsCancellationRequested){temp += i;}else{break;}}Console.WriteLine(temp); }); Thread.Sleep(200); clt.Cancel();
View Code
Task返回值
具有返回值的是要用泛型 指定返回值类型。
Task<int> t = new Task<int>(() => 5); t.Start(); Console.WriteLine(t.Result);TaskFactory<int> tf = new TaskFactory<int>(); var tft= tf.StartNew(() => { return 6; }); Console.WriteLine(tft.Result);
View Code
最后通过Task.Result得到结果。这个操作会卡着线程,一直等待回去结果。
Parallel并行任务
1、Parallel 定义:提供对并行循环和区域的支持。静态类,静态方法。他是基于Task,线程池。
其实是操作循环任务,但是循环的任务都是在平行执行的,没人先后顺序,但是,循环结会等待他们都结束的。
Parallel.For
Parallel.ForEach
Parallel.Invok
优点:主线程也会参与计算,缺点:就是会waitall 会卡住当前线程。
2、ParallelLoopResult 定义:提供执行 System.Threading.Tasks.Parallel 循环的完成状态。其实就是For和ForEach的返回值
3、ParallelLoopState 定义:可用来使 System.Threading.Tasks.Parallel 循环的迭代与其他迭代交互。此类的实例由 Parallel 类提供给每个循环;不能在您的用户代码中创建实例。
他可以让循环退出 ,通知。 (就像for循环中的bread)
4、ParallelOptions 定义:存储用于配置 System.Threading.Tasks.Parallel 类的方法的操作的选项。
// // 摘要: // 获取或设置与此 System.Threading.Tasks.ParallelOptions 实例关联的 System.Threading.CancellationToken。 // // 返回结果: // 与此实例关联的标记。 public CancellationToken CancellationToken { get; set; } // // 摘要: // 获取或设置此 System.Threading.Tasks.ParallelOptions 实例所允许的最大并行度。 // // 返回结果: // 一个表示最大并行度的整数。 // // 异常: // T:System.ArgumentOutOfRangeException: // 该属性被设置为 0 或小于 -1 的值。 public int MaxDegreeOfParallelism { get; set; } // // 摘要: // 获取或设置与此 System.Threading.Tasks.ParallelOptions 实例关联的 System.Threading.Tasks.TaskScheduler。将此属性设置为 // null,以指示应使用当前计划程序。 // // 返回结果: // 与此实例关联的任务计划程序。 public TaskScheduler TaskScheduler { get; set; }
View Code
可以取消任务,并行的数量(循环中一次并行执行任务的个数,当任务量比较大的时候,一定要指定这个值,不然电脑可能撑不住。但是他是基于线程池的,线程池会帮我们控制一下,但是还是会卡电脑。并行数量控制,导致起的线程是一轮一轮的,每一轮第一个线程ID都一样,用的主线程ID)
5、总结
Parallel.For()和Paraller.ForEach()方法在每次迭代中调用相同的代码,而Parallel.Invoke()方法允许同时调用不同的方法。Parallel.ForEach()用于数据并行性,Parallel.Invoke()用于任务并行性;
主线程可以参与计算,但是要waitall。等待。
Await Async
1、出现介绍
C#5.0 C#语言版本
.net fromwork 4.5 框架类库版本FCL
clr4.0 CLR版本
await async他是一个语法糖。什么是语法糖呢,就是c#或者.net fromwork改变但是clr没有改变。
泛型就不是语法糖,他出现的时候clr重写了,就是使用泛型的地方, 对应的生成相应的类型方法。
没有task就没有await async
2、原理
是一个语法糖,利用一个状态机的概念,通过编译器编译把await后面的代码封装为一个委托进行回调执行,并且await会等待执行完成,状态机就是这一个执行完之后,就movenest执行下一个回调。就是await一层层的嵌套就可以了。
3、使用
await只能出现在task前面,await后面的代码变成task的回调。快速的写出了异步回调
返回值只能是void task task<>,推荐使用task<>返回值,并封装通用T类型。
本文代码下载
补充例子
转载于:https://www.cnblogs.com/wudequn/p/7571039.html
多线程-Task、await/async相关推荐
- C#多线程和异步(二)——Task和async/await详解
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- C#多线程和异步(二)——Task和async/await详解(转载)
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- NET(C#):await返回Task的async方法
一. FrameWork 4.0之前的线程世界 在.NET FrameWork 4.0之前,如果我们使用线程.一般有以下几种方式: 使用System.Threading.Thread 类,调用 ...
- .NET(C#):await返回Task的async方法
一. FrameWork 4.0之前的线程世界 在.NET FrameWork 4.0之前,如果我们使用线程.一般有以下几种方式: 使用System.Threading.Thread 类,调用 ...
- Task和async/await详解
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- 【转】Task和async/await详解
一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...
- C# Task和async/await详解
C# Task和async/await详解 什么是异步 Task介绍 1 Task创建和运行 2 Task的阻塞方法(Wait/WaitAll/WaitAny) 1 Thread阻塞线程的方法 2 T ...
- 使用await / async时,HttpClient.GetAsync(...)永远不会返回
本文翻译自:HttpClient.GetAsync(-) never returns when using await/async Edit: This question looks like it ...
- await,async 我要把它翻个底朝天,这回你总该明白了吧
一:背景 1. 讲故事 await,async 这玩意的知识点已经被人说的烂的不能再烂了,看似没什么好说的,但我发现有不少文章还是从理论上讲述了这两个语法糖的用法,懂得还是懂,不懂的看似懂了过几天又不 ...
最新文章
- springboot之jackson的两种配置方式
- AIX性能管理指南-luoqiangb@dc
- 计算机网络运输层习题5-17
- 政务外网001---政务外网介绍
- python爬取图文新闻_python爬取新闻需要什么软件
- 转:短小强悍的JavaScript异步调用库
- Mac下Zookeeper安装及配置
- 8个免费、可商用的视频素材网站,一定要收藏
- 化繁为简:Swift剔除数组中重复元素的几种姿势
- 微信开发者工具 the permission value is offline verifying 异常
- android markdown 笔记,安卓-纯纯写作 | 快速笔记 Markdown
- Domino V12 Beta新玩法
- 独家发布!java总结与心得,下载量瞬秒百万
- 在测试tensorBroad中在运行mnist_with_summaries.py时URLError:urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答
- 商城系统开发,使用微信服务号好?还是小程序?
- centos7升级Apache2.4.6到2.4.54
- beautiful_sky(Bugku)
- python爬虫:批量抓取代理ip,进行验证,抓取豆瓣网站影视信息
- MIPI CSI-2笔记(2) -- 物理层Physical Layer
- AppUI自动化测试效率提升方案
热门文章
- 第1章-导言-习题1.13-1.17
- helloword,认真就输了
- 【软件使用】Windows下的Objective-C集成开发环境搭建(IDE)
- 解决ftp的pasv模式下iptables设置问题
- 解决ntfs格式的移动硬盘mount到Linux下时变成只读文件系统的问题
- 批处理判断文件夹是否存在
- asp.net页面中hmtl注释的问题
- 可变参数表 C语言 多态,C语言可变长参数实现“多态”.pdf
- linux 8051 编译,[编译] 3、在Linux下搭建51单片机的开发烧写环境(makefile版)
- 数据库存储数据的特点