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 引入了一个简化的方法, ...
随机推荐
- 在浏览器中输入www.baidu.com后执行的全部过程
1.客户端浏览器通过DNS解析到www.baidu.com 的IP地址220.181.27.48,通过这个IP地址找到客户端到服务器的路径.客户端浏览器发起一个HTTP会话到220.181.27.48 ...
- 第七章:四大组件之Service
Service是Android系统中的一种组件,它跟Activity的级别差不多,但是它不能自己运行,只能后台运行,并且可以和其他组件进行交互.Service是没有界面的长生命周期的代码.Servic ...
- Unity3D鼠标坐标转世界坐标和局部坐标
鼠标坐标转世界坐标和局部坐标: Vector3 MousePosition2Local () { mousePosition = Input.mousePosition; //获取屏幕坐标 mouse ...
- iOS ipa包瘦身,iOS8及以下text段超60MB
前沿 很早之前写过一篇相关文章,不过博客主机上跑路了之后数据没了,凭着记忆补了下相关资料 ipa安装包瘦身 清理无用图片,图片压缩(PNG换WebP和JPG),处于某种不可抗拒的原因,导致有部分3X图 ...
- 【PyTorch深度学习60分钟快速入门 】Part5:数据并行化
在本节中,我们将学习如何利用DataParallel使用多个GPU. 在PyTorch中使用多个GPU非常容易,你可以使用下面代码将模型放在GPU上: model.gpu() 然后,你可以将所有张 ...
- Struts的FormFile与Commons-FileUpload控件使用心得
转自: http://www.iteye.com/topic/212566 前一段时间刚来公司,看到一个项目中以前有人写的struts代码.是使用了FormFile来处理关于文件上传的模块.但是用力一 ...
- 将文件内容隐藏在bmp位图中
首先要实现这个功能,你必须知道bmp位图文件的格式,这里我就不多说了,请看:http://www.cnblogs.com/xiehy/archive/2011/06/07/2074405.html 接 ...
- Struts2学习(六)———— 文件上传和下载
一.单文件上传 在没学struts2之前,我们要写文件上传,非常麻烦,需要手动一步步去获取表单中的各种属性,然后在进行相应的处理,而在struts2中就不需要了,因为有一个fileUpload拦截器帮 ...
- FFmpeg数据结构AVBuffer
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10399048.html AVBuffer是FFmpeg中很常用的一种缓冲区,缓冲区使用引 ...
- python的Web框架,类视图
类视图 范式 from django.views import View # 继承View class IndexView(View): def get(self, request): #写法和函数视 ...