.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 异步程序开发的更多相关文章

  1. C# 异步编程1 APM模式异步程序开发

    C#已有10多年历史,单从微软2年一版的更新进度来看活力异常旺盛,C#中的异步编程也经历了多个版本的演化,从今天起着手写一个系列博文,记录一下C#中的异步编程的发展历程.广告一下:喜欢我文章的朋友,请 ...

  2. 搞定 CompletableFuture,并发异步编程和编写串行程序还有什么区别?你们要的多图长文

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  3. Linux网络编程:基于UDP的程序开发回顾篇

    基于无连接的UDP程序设计 同样,在开发基于UDP的应用程序时,其主要流程如下:   对于面向无连接的UDP应用程序在开发过程中服务端和客户端的操作流程基本差不多.对比面向连接的TCP程序,服务端少了 ...

  4. Linux网络编程:基于TCP的程序开发回顾篇《转》

    面向连接的TCP程序设计 基于TCP的程序开发分为服务器端和客户端两部分,常见的核心步骤和流程: 其实按照上面这个流程调用系统API确实可以完全实现应用层程序的开发,一点问题没有.可随着时间的推移,你 ...

  5. 深入理解JS异步编程五(脚本异步加载)

    异步脚本加载 阻塞性脚本 JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析.渲染以及其他资源的下载都要停下来等待脚本执行完毕 浏览器是 ...

  6. C# 异步编程2 EAP 异步程序开发

    在前面一篇博文记录了C# APM异步编程的知识,今天再来分享一下EAP(基于事件的异步编程模式)异步编程的知识.后面会继续奉上TPL任务并行库的知识,喜欢的朋友请持续关注哦. EAP异步编程算是C#对 ...

  7. .Net Core WebAPI 基于Task的同步&异步编程快速入门

    .Net Core WebAPI 基于Task的同步&异步编程快速入门 Task.Result async & await 总结 并行任务(Task)以及基于Task的异步编程(asy ...

  8. 使用 Async 和 Await 的异步编程(C# 和 Visual Basic)[msdn.microsoft.com]

    看到Microsoft官方一篇关于异步编程的文章,感觉挺好,不敢独享,分享给大家. 原文地址:https://msdn.microsoft.com/zh-cn/library/hh191443.asp ...

  9. Async 、 Await 的异步编程(.NET 4.5 新异步模型) [转自MSDN]

    使用异步编程,可以避免性能瓶颈和增强应用程序的总体响应能力. 但是,编写异步应用程序的以前的技术可能比较复杂,使它们难以编写,调试和维护. Visual Studio 2012 引入了一个简化的方法, ...

随机推荐

  1. win10 + gluon + GPU

    1. 下载教程 可以用浏览器下载zip格式并解压,在解压目录文件资源管理器的地址栏输入cmd进入命令行模式. 也可以 git pull https://github.com/mli/gluon-tut ...

  2. IDEA里五种目录类型简介(Mark Directory as)

    通过File  -> Settings-project Structure-Modules 或者右键Mark Directory as可以找到这五种类型. Sources 一般用于标注类似 sr ...

  3. C# TableLayoutPanel使用方法

    一.利用TableLayoutPanel类展示表格,以10行5列为例 第1步:在前台创建一个panel,使TableLayoutPanel对象填充其内部. 第2步:创建TableLayoutPanel ...

  4. Python 解析har 文件将域名分类导出

    前言 作为程序员平时主要是使用 shadowsocks 作为代理工具的.shadowsocks 有个很明显的优点儿就是可以设置白名单和黑名单.白名单是会走shadowsocks的自动代理模式. 遇到的 ...

  5. Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

    前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...

  6. win32编程简介

    win32编程简介 复习Win32整理下知识. 为什么学习win32? 我们要编写windos程序.都离不开API. 也就是我们所说的win32程序. 所以学好win32是你能不能再windows下编 ...

  7. 内核知识第六讲,内核编写规范,以及获取GDT表

    内核知识第六讲,内核编写规范,以及获取GDT表 一丶内核驱动编写规范 我们都知道,在ring3下,如果我们的程序出错了.那么就崩溃了.但是在ring0下,只要我们的程序崩溃了.那么直接就蓝屏了. 那么 ...

  8. git第九节---git命令实战

    1. git 项目创建 mkdir git-command 2.git 配置 git config --list 配置用户名 邮箱 git config user.name 'XXX'  --loca ...

  9. jquery中innerwidth,outerwidth,outerwidth和width的区别

    在jQuery中,width()方法用于获得元素宽度: innerWidth()方法用于获得包括内边界(padding)的元素宽度, outerWidth()方法用于获得包括内边界(padding)和 ...

  10. ASP.NET Identity 二 (转载)

    来源:http://www.cnblogs.com/r01cn/p/5180892.html#undefined 推荐看原文,这里转载是怕好文章消失了. 注:本文是[ASP.NET Identity系 ...