C# 异步编程3 TPL Task 异步程序开发
.Net在Framework4.0中增加了任务并行库,对开发人员来说利用多核多线程CPU环境变得更加简单,TPL正符合我们本系列的技术需求。因TPL涉及内容较多,且本系列文章为异步程序开发,所以本文并未涉及TPL全部内容。后续会写一个TPL系列的Blog,各位朋友可以关注一下。
TASK
TPL的基础Task,Task是TPL并行编程的最小单元,即表示一个异步操作。利用Task进行异步编程非常简单:
static void Main(string[] args)
{
BaseTaskDemo();
//BaseTaskDemo2();//两者效果相同
Console.WriteLine(String.Format("Main 线程:{0}", Thread.CurrentThread.ManagedThreadId));
Console.ReadLine();
}
private static void BaseTaskDemo()
{
var task = new Task(() => {
Thread.Sleep();
Console.WriteLine(String.Format("Task 线程:{0}", Thread.CurrentThread.ManagedThreadId));
});
task.Start();
}
private static void BaseTaskDemo2()
{
var task = Task.Run(() =>
{
Thread.Sleep();
Console.WriteLine(String.Format("Task 线程:{0}", Thread.CurrentThread.ManagedThreadId));
});
}
程序说明:
1、new Task(Action)创建一个异步任务,参数Action是异步任务要执行的委托对象
2、task.Start()启动异步任务的执行
3、Task.Run(Action)等效于1、2的组合
上面的示例程序实现了异步操作,但主线程无法获知异步任务完成与否。为获取Task的执行结果,上面的程序进行如下修改:
static void Main(string[] args)
{
var task = TaskForResult();
Console.WriteLine(String.Format("Main 线程:{0}", Thread.CurrentThread.ManagedThreadId));
task.Wait();
if (task.IsCompleted)
Console.WriteLine(String.Format("获取异步执行结果:{0}", task.Result));
Console.ReadLine();
}
private static Task<int> TaskForResult()
{
var task = Task.Run(()=> {
Thread.Sleep();
Console.WriteLine(string.Format("Task 线程:{0},Task执行完成。", Thread.CurrentThread.ManagedThreadId));
return ;
});
return task;
}
程序说明:
1、下面代码的原型为Task.Run(Func<int>),Run的参数不再是Action,因为在该任务中我们要返回一个int值,所以应该使用Run(Func<T>)这个重载。
var task = Task.Run(()=> {
Thread.Sleep(2000);
Console.WriteLine(string.Format("Task 线程:{0},Task执行完成。", Thread.CurrentThread.ManagedThreadId));
return 10;
});
2、主线程中调用task.Wait()时,主线程将一直等待异步任务完成或被取消。
3、task.IsCompleted属性用于判断异步任务是否完成
4、task.Result获取异步任务的执行结果(返回值)
上面的示例程序已经实现了主线程获取异步程序的状态及返回值,但如果异步程序非常耗时,则存在主线程需要临时取消耗时异步程序执行的功能。为了满足上述要求,程序可做如下调整:
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
var task = TaskForResult2(tokenSource);
Console.WriteLine(String.Format("Main 线程:{0}", Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(String.Format("Main 线程:{0},获取异步执行结果:{1}", Thread.CurrentThread.ManagedThreadId, task.Result));
Console.ReadLine();
}
private static Task<int> TaskForResult2(CancellationTokenSource tokenSource)
{
var task = Task.Run(() =>
{
Thread.Sleep();
if (!tokenSource.IsCancellationRequested)
{
Console.WriteLine(String.Format("Task 线程:{0},任务1执行完成。", Thread.CurrentThread.ManagedThreadId));
return ;
}
else
{
return -;
}
}, tokenSource.Token);
return task;
}
程序说明:
1、CancellationTokenSource提供任务取消消息,构造参数 5000 表示CancellationTokenSource在发出5s后超时并取消
2、在Task的委托内部 tokenSource.IsCancellationRequested 获取取消标记
3、task.Result会隐式调用Wait()方法
如果异步Task在执行过程中出现异常,则需要对发生的异常做出响应:
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
var task = TaskForResult2(tokenSource);
Console.WriteLine(String.Format("Main 线程:{0}", Thread.CurrentThread.ManagedThreadId));
try
{
//task.Wait();
Console.WriteLine(String.Format("Main 线程:{0},获取异步执行结果:{1}", Thread.CurrentThread.ManagedThreadId, task.Result));
}
catch (AggregateException ex)
{ }
Console.ReadLine();
}
private static Task<int> TaskForResult2(CancellationTokenSource tokenSource)
{
var task = Task.Run(() =>
{
Thread.Sleep();
if (!tokenSource.IsCancellationRequested)
{
throw new Exception("抛出异常");
}
else
{
return -;
}
}, tokenSource.Token);
return task;
}
程序说明:
1、在Task中引发的异常需要在 task.Wait()或task.Result时捕获
写在后面:Task的功能远不止上述这些,如Task多任务串行、TaskFactory、Paralle等知识非常有趣和重要。如果你感兴趣的话,可以关注本人后续TPL的文章。
C# 异步编程3 TPL Task 异步程序开发的更多相关文章
- C# 异步编程1 APM模式异步程序开发
C#已有10多年历史,单从微软2年一版的更新进度来看活力异常旺盛,C#中的异步编程也经历了多个版本的演化,从今天起着手写一个系列博文,记录一下C#中的异步编程的发展历程.广告一下:喜欢我文章的朋友,请 ...
- 搞定 CompletableFuture,并发异步编程和编写串行程序还有什么区别?你们要的多图长文
你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...
- Linux网络编程:基于UDP的程序开发回顾篇
基于无连接的UDP程序设计 同样,在开发基于UDP的应用程序时,其主要流程如下: 对于面向无连接的UDP应用程序在开发过程中服务端和客户端的操作流程基本差不多.对比面向连接的TCP程序,服务端少了 ...
- Linux网络编程:基于TCP的程序开发回顾篇《转》
面向连接的TCP程序设计 基于TCP的程序开发分为服务器端和客户端两部分,常见的核心步骤和流程: 其实按照上面这个流程调用系统API确实可以完全实现应用层程序的开发,一点问题没有.可随着时间的推移,你 ...
- 深入理解JS异步编程五(脚本异步加载)
异步脚本加载 阻塞性脚本 JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析.渲染以及其他资源的下载都要停下来等待脚本执行完毕 浏览器是 ...
- C# 异步编程2 EAP 异步程序开发
在前面一篇博文记录了C# APM异步编程的知识,今天再来分享一下EAP(基于事件的异步编程模式)异步编程的知识.后面会继续奉上TPL任务并行库的知识,喜欢的朋友请持续关注哦. EAP异步编程算是C#对 ...
- .Net Core WebAPI 基于Task的同步&异步编程快速入门
.Net Core WebAPI 基于Task的同步&异步编程快速入门 Task.Result async & await 总结 并行任务(Task)以及基于Task的异步编程(asy ...
- 使用 Async 和 Await 的异步编程(C# 和 Visual Basic)[msdn.microsoft.com]
看到Microsoft官方一篇关于异步编程的文章,感觉挺好,不敢独享,分享给大家. 原文地址:https://msdn.microsoft.com/zh-cn/library/hh191443.asp ...
- Async 、 Await 的异步编程(.NET 4.5 新异步模型) [转自MSDN]
使用异步编程,可以避免性能瓶颈和增强应用程序的总体响应能力. 但是,编写异步应用程序的以前的技术可能比较复杂,使它们难以编写,调试和维护. Visual Studio 2012 引入了一个简化的方法, ...
随机推荐
- 11-部署Heapster插件
配置和安装 Heapster 到 heapster release 页面 下载最新版本的 heapster. $ wget https://github.com/kubernetes/heapster ...
- HttpServletRequest简介
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息. 常用方 ...
- 【xsy1503】 fountain DP
题目大意:给你$D$个格子,有$n$个喷水器,每个喷水器有一个喷水距离$r_i$. 现在你需要在这$D$个格子中选择$n$个位置按照任意顺序安装这$n$个喷水器,需要满足$n$个喷水器互相喷不到对方. ...
- .net core在Linux下获取AD域信息
.net core在Linux下获取AD域信息 .net Core 2.1.4 .net core现在System.DirectoryServices只支持Windows平台下使用. 参考: http ...
- Intellij-忽略其他编译错误,运行当前文件
在使用Intellij IDEA的时候,有时候想在项目中写个main()方法或者单元测试测试个功能,但是有其他文件编译出错IDEA就提示我说不能运行,很是烦恼. 能不能像Eclipse一样呢,其他编译 ...
- Java 范例 - 字节处理
前言 Java 编程中常会遇到需要进行字节处理的地方,本篇文章就来探讨编程中会遇到的字节处理问题. 字节序 字节序(endianness)是对于多字节数据来说的,它描述了多字节数据存储的顺序,分为大端 ...
- Spring Boot + Spring Cloud 实现权限管理系统 后端篇(二十一):服务网关(Zuul)
在线演示 演示地址:http://139.196.87.48:9002/kitty 用户名:admin 密码:admin 技术背景 前面我们通过Ribbon或Feign实现了微服务之间的调用和负载均衡 ...
- 扩展方法IEnumerable<T>转换为IList<SelectListItem> ,提供@Html.DropDownList使用
由于在MVC中经常会使用到@Html.DropDownList方法,而该方法接收的是List<SelectListItem> 参数,因此就想着写一个扩展方法,直接把IEnumerable转 ...
- 本地k8s环境minikube搭建过程
首先要安装docker这个环境是需要自己安装的.相关步骤如下: 1 2 3 4 5 6 7 8 9 10 11 yum install -y yum-utils device-mapper-persi ...
- php 常用$_SERVER变量列表
$_SERVER['HTTP_ACCEPT_LANGUAGE'] //浏览器语言 $_SERVER['REMOTE_ADDR'] //当前用户 IP . $_SERVER['REMOTE_HOST'] ...