浅谈Task的用法
Task是用来实现多线程的类,在以前当版本中已经有了Thread及ThreadPool,为什么还要提出Task类呢,这是因为直接操作Thread及ThreadPool,向线程中传递参数,获取线程的返回值及线程当启停都非常的麻烦,所以微软的工程师对Thread进行了再封装,这就是Task,可以这么说Task是架构在Thread之上的,
所以多线程时Task是我们的首选。
Task类和Task<TResult>类,后者是前者的泛型版本。TResult类型为Task所调用方法的返回值。
主要区别在于Task构造函数接受的参数是Action委托,而Task<TResult>接受的是Func<TResult>委托
Task(Action)
Task<TResult>(Func<TResult>)
一、Task的声明
Task的声明有两种方式:
a,通过new 的方式来声明
Task objTask = new Task();
b.通过Task.Factory.StartNew的方式来声明
Task.Factory.StartNew(MyMethod);
这两种声明方式的区别,第一种声明方式开启线程必须使用objTask.Start(),而通过Task.Factory.StartNew的方式则不用。
二、Task常用方法
a.启动一个任务
static void Main(string[] args)
{
Task Task1 = new Task(() => Console.WriteLine("Task1"));
Task1.Start();
Console.ReadLine();
}
通过实例化一个Task对象,然后Start,这种方式中规中矩,但是实践中,通常采用更方便快捷的方式
Task.Run(() => Console.WriteLine("Foo"));
这种方式直接运行了Task,不像上面的方法还需要调用Start();
Task.Run方法是Task类中的静态方法,接受的参数是委托。返回值是为该Task对象。
Task.Run(Action)
Task.Run<TResult>(Func<Task<TResult>>)
Task构造方法还有一个重载函数如下:
Task 构造函数 (Action, TaskCreationOptions),对应的Task泛型版本也有类似构造函数。TaskCreationOptions参数指示Task创建和执行的可选行为。常用的参数LongRunning。
b.任务等待
默认情况下,Task任务由线程池异步执行,想要知道Task任务是否完成,可以通过Task.IsComplated属性获得
也可以使用Task.Wait()方法来等待线程的完成,Task.Wait()方法会阻塞当前线程。
static void Main(string[] args)
{
Task Task1=Task.Run(() => { Thread.Sleep();
Console.WriteLine("Foo");
Thread.Sleep();
});
Console.WriteLine(Task1.IsCompleted);
Task1.Wait();//阻塞当前线程
Console.WriteLine(Task1.IsCompleted);
}
还需要说的是,Wait方法有个重构方法,签名如下:public bool Wait(int millisecondsTimeout),接受一个时间。如果在设定时间内完成就返回true,否则返回false。如下的代码:
static void Main(string[] args)
{
Task Task1=Task.Run(() => { Thread.Sleep();
Console.WriteLine("Foo");
Thread.Sleep();
}); Console.WriteLine("Task1.IsCompleted:{0}",Task1.IsCompleted);
bool b=Task1.Wait();
Console.WriteLine("Task1.IsCompleted:{0}", Task1.IsCompleted);
Console.WriteLine(b);
Thread.Sleep();
Console.WriteLine("Task1.IsCompleted:{0}", Task1.IsCompleted);
}
输出的结果为:

C.获取返回值
要获得返回值,就要用到Task的泛型版本了。 说到Task的返回值就不得不说await和async关键字了。
当函数使用async标记后,返回值必须为void,Task,Task<T>,当返回值为Task<T>时,函数内部只需要返回T类型,编译器会自动包装成Task<T>类型
await关键字必须在具有async标记的函数内使用。举个例子:
static void Main(string[] args)
{
Console.WriteLine("调用主线程");
Task<string> s = Testasync();
Console.WriteLine(s.Result);
Console.ReadKey(); }
static async Task<string> Testasync()
{
Console.WriteLine("运行Task之前" + Thread.CurrentThread.ManagedThreadId); Task<string> t= Task.Run<string>(() =>
{
Console.WriteLine("运行Task" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep();
return "我是测试线程";
});
Console.WriteLine("运行Task之后" + Thread.CurrentThread.ManagedThreadId);
var result = await t;
return result;
}
从运行结果可以看出:
1)在async标识的方法体里面,如果没有await关键字的出现,那么这种方法和调用普通的方法没什么区别(就是说async和await是成对出现的,没有await的async是没有意义的)
(2)在async标识的方法体里面,在await关键字出现之前,还是主线程顺序调用的,直到await关键字的出现才会出现线程阻塞。
(3)await关键字可以理解为等待方法执行完毕,除了可以标记有async关键字的方法外,还能标记Task对象,表示等待该线程执行完毕。所以await关键字并不是针对于async的方法,而是针对async方法所返回给我们的Task。
D.延续任务
所谓延续任务,就是说在任务执行完成之后继续执行任务,有两种方法
第一种,使用一种是使用GetAwaiter方法。GetAwaiter方法返回一个TaskAwaiter结构,该结构有一个OnCompleted事件,只需对OnCompleted事件赋值,即可在完成后调用该事件。
static void Main(string[] args)
{
Task<int> Task1 = Task.Run<int>(() => { return Enumerable.Range(, ).Sum(); });
var awaiter = Task1.GetAwaiter();
awaiter.OnCompleted(() =>
{
Console.WriteLine("Task1 finished");
int result = awaiter.GetResult();
Console.WriteLine(result); // Writes result
});
Thread.Sleep();
}
第二种,使用ContinueWith方法
ContinueWith返回的任然是一个Task类型。ContinueWith方法有很多重载,算上泛型版本,差不多40个左右的。其中最常用的,就是接受一个Action或者Func委托,而且,这些委托的第一个传入参数都是Task类型,即可以访问先前的Task对象。示例:
static void Main(string[] args)
{
Task<int> Task1 = Task.Run<int>(() => {return Enumerable.Range(, ).Sum(); });
Task1.ContinueWith(antecedent => {
Console.WriteLine(antecedent.Result);
Console.WriteLine("Runing Continue Task");
});
Thread.Sleep();
}
E,延迟任务
Task.Delay()方法是相当于异步的Thread.Sleep();
浅谈Task的用法的更多相关文章
- 新手浅谈Task异步编程和Thread多线程编程
初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...
- 浅谈localStorage的用法
今天接到一个任务,说是让自动调节textarea标记的输入高度,而且还要记录下来,下次登录的时候还是调节后的高度,我第一时间就想到了localStorage的用法,直接代码献上: <html l ...
- C#异步编程之浅谈Task
上一篇讲到了.Net4.5新增的async和await关键字,其实async和await算是一组标记,真正实现异步操作的是Task新开的任务线程. 什么是Task Task是.Net4.0新增用来处理 ...
- Linux之浅谈VIM常见用法及原理图
本次归纳以强大的VIM文本处理工具常见用法去展开论述. 文本编辑种类: 行编辑器:sed 全屏编辑器:nano,vi vim - Vi改进 其他编辑器: ...
- 浅谈intval()函数用法
<? } } 总结:intval()函数功能1.参数一定是数字否则会报错,2.如果是数字那一定是整数,如果有小点,那会省略掉,3,强调参数可以有“-”值.4.参数第一位不应为0开头,不然会自动转 ...
- 浅谈AutoResetEvent的用法
using System;using System.Threading; namespace AutoResetEvent_Examples{ class MyMainClass { ...
- 浅谈background的用法
div css 背景样式background属性 一.语法及参数 1.语法:background : background-color(颜色) || background-image(图片地址) || ...
- 浅谈Python在信息学竞赛中的运用及Python的基本用法
浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...
- 浅谈@RequestMapping @ResponseBody 和 @RequestBody 注解的用法与区别
浅谈@RequestMapping @ResponseBody 和 @RequestBody 注解的用法与区别 Spring 2.5 版本新增了注解功能, 通过注解,代码编写简化了很多:但熟悉注解的使 ...
随机推荐
- iOS学习——iOS 宏(define)与常量(const)的正确使用
概述 在iOS开发中,经常用到宏定义,或用const修饰一些数据类型,经常有开发者不知怎么正确使用,导致项目中乱用宏与const修饰.你能区分下面的吗?知道什么时候用吗? #define HSCode ...
- Appium+Python+Genymotion ------环境配置
前言 之前总是在找方向,也研究了很多的工具,终于找到了适合自己的一套,打算把学习的过程做一个记录,给自己加深印象,也希望能给其他人一些帮助. 一.工具准备 1.Appium // http://a ...
- 台式机主机u盘安装centos7报错及注意事项
利用UltraISO制作U盘启动安装台式机CentOS7系统:流程及报错解决 一.制作U盘 1.首先打开UltraISO软件,尽量下载最新版的 2.点击工具栏中的第二个打开镜像文件工具,如图红色方框标 ...
- 求平方根算法 Heron’s algorithm
求平方根问题 概述:本文介绍一个古老但是高效的求平方根的算法及其python实现,分析它为什么可以快速求解,并说明它为何就是牛顿迭代法的特例. 问题:求一个正实数的平方根. 给定正实数 \(m\),如 ...
- The Best Path(HDU5883)[欧拉路]2016青岛online
题库链接:http://acm.hdu.edu.cn/showproblem.php?pid=5883 欧拉回路裸题,第一次接触欧拉路的我是真的长见识了^-^ 懂了欧拉路这道题就是没什么问题了,欧拉路 ...
- 如何使用有道云笔记的Markdown----初级版?
我一般整理笔记用的是用有道云笔记,在这里,Markdown怎么用? 什么是Markdown?Markdown是一种轻量级的「标记语言」,通常为程序员群体所用,目前它已是全球最大的技术分享网站 GitH ...
- OpenCvSharp 通过特征点匹配图片
现在的手游基本都是重复操作,一个动作要等好久,结束之后继续另一个动作.很麻烦,所以动起了自己写一个游戏辅助的心思. 这个辅助本身没什么难度,就是通过不断的截图,然后从这个截图中找出预先截好的能代表相应 ...
- [Swoole入门到进阶] [精选公开课] Swoole服务器-Server的四层生命周期
PHP 完整生命周期 执行PHP文件 PHP扩展模块初始化(MINIT) PHP扩展请求初始化(RINIT) 执行 PHP 逻辑 PHP扩展请求结束(RSHUTDOWN) PHP脚本清理 PHP扩展模 ...
- 不要小看小小的 emoji 表情
前言 好久没更新了,最近事比较多,或许下个月就会恢复到正常的发文频次. 这篇文章得从一个 emoji 表情开始,我之前开源的一个 IM 项目中有朋友提到希望可以支持 emoji 表情传输. https ...
- CentSO7.6下部署Maridb Galera Cluster 实践记录(一)
根据目前系统业务发展,预计未来上集成的概率异常之高,所以提前学习如何部署,网上尽管有很多这方面资料,但是真正适合自己的只有实践过的. 很奇怪目前的yum资源库里面为什么没有galera资源,目前只能通 ...