惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Help Net Security
Help Net Security
G
Google Developers Blog
雷峰网
雷峰网
WordPress大学
WordPress大学
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Engineering at Meta
Engineering at Meta
Security Latest
Security Latest
T
Threat Research - Cisco Blogs
AWS News Blog
AWS News Blog
F
Full Disclosure
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Exploit Database - CXSecurity.com
J
Java Code Geeks
U
Unit 42
C
Cyber Attacks, Cyber Crime and Cyber Security
V
V2EX
C
Cisco Blogs
博客园 - 司徒正美
Project Zero
Project Zero
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
Scott Helme
Scott Helme
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
S
Securelist
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
T
Threatpost
Recorded Future
Recorded Future
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
The Register - Security
The Register - Security
S
Security Archives - TechRepublic
博客园 - Franky
N
News | PayPal Newsroom
Simon Willison's Weblog
Simon Willison's Weblog
S
SegmentFault 最新的问题
W
WeLiveSecurity
A
Arctic Wolf
B
Blog

博客园 - lsyyx

SQL Server 2008中SQL增强之三:Merge(在一条语句中使用Insert,Update,Delete) SQL Server 2008中SQL增强之二:Top新用途 SQL Server 2008中SQL增强之一:Values新用途 SQL Server 2008中增强的汇总技巧 需要弥补的那部分SQL oracle递归查询\sqlserver递归 - lsyyx - 博客园 如何写SQL,计算上下记录同一字段相差值 SQL语句整理资料 Sqlserver Update 用法 可判断datatable的列是否有重复 Oracle:ODP.NET Managed 小试牛刀 (转) Asp.Net4.0/VS2010新变化(4):SEO的改进 Asp.Net4.0/VS2010新变化(2):网站自动预热 Asp.Net4.0/VS2010新变化(3):webform中也可以直接url路由 NET4.0中非常好用的一个东西Tuple 关于.net4.0中的Action委托 .NET4.0多线程编程---Cooperative Cancellation net4.0新特性之线程同步 C#4.0语言新功能及应用 (1)
NET4.0多线程编程---Tasks
lsyyx · 2014-10-23 · via 博客园 - lsyyx

写在前面的话

  不得不说4.0里面新增的task实在是让人耳目一新,曾经在thread里面查找当线程abort等等操作的时候有没有相应的事件,就像gridview在分页、绑定的时候会产生事件一样,但是在thread里面是没有找到。然而task里面这些都实现了,虽然不是以事件的方式实现,但是它真的实现了。很让人兴奋。

一、概述 

  在上一篇文章.NET4.0多线程编程---Cooperative Cancellation提到线程池没有提供任何内在的方法告诉我们操作什么时候完成,在线程完成了以后,我们也没有任何方法可以获取一个返回值。

  为了弥补上述不足,微软在.NET4.0里面提出了任务的概念(Task),下面的两种方式产生的结果是一样的

ThreadPool.QueueUserWorkItem(Sum, 5);//使用线程池 new Task(Sum, 5).Start();//使用Task

  上面线程池是由cpu自己操作的,而task需要程序手动去Start。

  对于task,在使用其构造函数的时候可以传递Action(向上面只传递没有参数的函数),也可以传递Action<object>(有参数的函数),还可以传递CancelationToken(用于接收取消的命令,这样描述感觉才对,token啊)

二、等待一个Task完成,并且获取其执行结果

  要想获取执行结果,我们必须构造一个Task<TResult>对象,TResult必须要和即将要和绑定的方法的返回值相匹配。等待调用其Wait方法。写了一个小例子。

复制代码

代码

namespace Alex.Net4MultiThread.MyTask { internal class OwnTask {
public static void Main() { Task<int> t = new Task<int>(n => Sum((int)n), 10); t.Start(); t.Wait();//等待 Console.WriteLine(t.Result);//900 } private static int Sum(int n) { int sum = 0; for (; n < 100; n++) { Thread.Sleep(10); sum += 10; } return sum; } }
}

复制代码

  在上面代码中如果在调用Wait时,task已经开始执行,那么程序会阻止当前线程一直等待到task完成为止(犹如thread所示)。而如果在调用wait时,task还没有开始执行,那么当前线程是不会阻止的。

  当在一个任务中产生异常,任务会正常返回,但是当调用Wait或者Result的时候系统会抛出System.AggregateException异常。

三、取消一个Task

  可是使用CancellationTokenSource来取消一个task,如果考虑到又可能要取消一个task,那么对应的方法应该接受一个CancellationToken参数(用于通知被取消)。上代码。

复制代码

代码

namespace Alex.Net4MultiThread.MyTask { internal class OwnTask {
public static void Main() { CancellationTokenSource cts = new CancellationTokenSource(); Task<int> t = new Task<int>(() => Sum(cts.Token, 10), cts.Token);
t.Start(); cts.Cancel();//取消 try { //在调用Wait或者Result时会返回目标操作中的异常 Console.WriteLine(t.Result);//900 } catch (AggregateException ex) { ex.Handle(e => e is OperationCanceledException); Console.WriteLine("Sum was canceled"); } } private static int Sum(CancellationToken ct, int n) { int sum = 0; for (; n < 100; n++) { ct.ThrowIfCancellationRequested();//如果被通知取消,则会抛出异常 sum += 10; } return sum; } } }

复制代码

  上面的操作真的是很让人激动的,比起Thread.Abort实在是太好了。对于取消。如果在取消时Task还没有Start,那么task将不会执行。

四、当其他任务完成的时候,自动开始一个新的任务

  在前面的例子中,我们wait一个task或者要获取一个task的Result,等待其实是很花费系统资源的,在Task编程模式下,大多时候我们都无需等待,只需注册一个新的task,该task在当前task完成时执行,此时我们可以对Result进行操作。

复制代码

代码

namespace Alex.Net4MultiThread.MyTask { internal class OwnTask {
public static void Main() { Task<int> t = new Task<int>(n=>Sum((int)n),10);
t.Start();// Task cwt = t.ContinueWith(task => Console.WriteLine("The sum is :"

           +task.Result));//900 Console.Read(); } private static int Sum(int n) { int sum = 0; for (; n < 100; n++) { sum += 10; } return sum; } } }

复制代码

  上面代码中新的任务(注册)是通过ContinueWith来完成的,该函数也返回一个task,但是一般情况下直接忽略其返回值,而应该将注意力集中在其逻辑,“注册什么,注册的task做什么,应该在什么时候让其执行。。。”,比如在上例中,注册的task在主task结束时打印出主task的执行结果。

  其实上面的代码是在主task完成之后执行某注册的task,其实ContinueWith函数还接受一个TaskContinuationOptions枚举参数。有8-9个值吧,我主要演示3个,具体功能如其名所示。

复制代码

代码

t.ContinueWith(task => Console.WriteLine("The sum is :"+task.Result), TaskContinuationOptions.OnlyOnRanToCompletion);//主task成功时执行当前产生的task t.ContinueWith(task => Console.WriteLine("The sum is :" + task.Result), TaskContinuationOptions.OnlyOnFaulted);//主task失败执行当前产生的task t.ContinueWith(task => Console.WriteLine("The sum is :" + task.Result), TaskContinuationOptions.OnlyOnCanceled);//主task取消执行当前产生的task

复制代码