.NET 并行(多核)编程系列之五 Task执行和异常处理
原文:.NET 并行(多核)编程系列之五 Task执行和异常处理
.NET 并行(多核)编程系列之五 Task执行和异常处理
前言:本篇主要讲述等待task执行完成。
本篇的议题如下:
1. 等待Task执行完成
2. Task中的异常处理
系列文章链接:
首先注意一点:这里提到的"等待"和之前文章提到的"休眠"意思是不一样的:
等待:在等待一个task的时候,这个task还是在运行之中的,"等待"相当于在监听运行的task的执行情况。
休眠:让tasku不运行。
在上篇文章中介绍了如果从Task中获取执行后的结果:在Task执行完成之后调用Task.Result获取。其实也可以用其他的方法等待Task执行完成而不获取结果,这是很有用的:如果你想等待一个task完成之后再去做其他的事情。而且我们还可以等待一个task执行完成,或者等待所有的task执行完成,或者等待很多task中的一个执行完成。因为Task是由内部的Scheduler管理的,调用wait方法,其实就是我们在监控task的执行,看看这个task是否执行完了,如果完成,那么wanit方法就返回true,反之。
1. 等待Task执行完成
1.1等待单独的一个Task执行完成
我们可以用Wait()方法来一直等待一个Task执行完成。当task执行完成,或者被cancel,或者抛出异常,这个方法才会返回。可以使用Wait()方法的不同重载。举个例子:
代码
}
}, token);
}
从上面的例子可以看出,wait方法子task执行完成之后会返回true。
注意:当在执行的task内部抛出了异常之后,这个异常在调用wait方法时会被再次抛出。后面再"异常处理篇"会讲述。
1.2.等待多个task
我们也可以用WaitAll()方法来一直到等待多个task执行完成。只有当所有的task执行完成,或者被cancel,或者抛出异常,这个方法才会返回。WiatAll()方法和Wait()方法一样有一些重载。
注意:如果在等在的多个task之中,有一个task抛出了异常,那么调用WaitAll()方法时就会抛出异常。
代码
}
Console.WriteLine("Task 1 complete");
}, token);
Task task2 = new Task(() =>
{
Console.WriteLine("Task 2 complete");
}, token);
// start the tasks
task1.Start();
task2.Start();
// wait for the tasks
Console.WriteLine("Waiting for tasks to complete.");
Task.WaitAll(task1, task2);
Console.WriteLine("Tasks Completed.");
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
在上面的例子中,首先创建了两个task,注意我们创建的是可以被cancel的task,因为使用CancellationToken。而且在第一个task中还是用waitOne()休眠方法,其实目的很简单:使得这个task的运行时间长一点而已。之后我们就调用了WaitAll()方法,这个方法一直到两个task执行完成之后才会返回的。
1.3.等待多个task中的一个task执行完成
可以用WaitAny()方法来等待多个task中的一个task执行完成。通俗的讲就是:有很多的task在运行,调用了WaitAny()方法之后,只要那些运行的task其中有一个运行完成了,那么WaitAny()就返回了。
代码
}
Console.WriteLine("Task 1 complete");
}, token);
Task task2 = new Task(() =>
{
Console.WriteLine("Task 2 complete");
}, token);
// start the tasks
task1.Start();
task2.Start();
// wait for the tasks
Console.WriteLine("Waiting for tasks to complete.");
int taskIndex = Task.WaitAny(task1, task2);
Console.WriteLine("Task Completed. Index: {0}", taskIndex);
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
2. Task中的异常处理
在并行编程(TPL)中另外一个已经标准化了的操作就是"异常处理"。而且在并行编程中异常处理显得尤为重要,因为并行编程时与系统中的线程相关的,出了异常,你开发的程序就很有可能崩溃。
下面就详细介绍TPL中异常处理操作。
a.处理基本的异常。
在操作task的时候,只要出现了异常,.NET Framework就会把这些异常记录下来。例如在执行Task.Wait(),Task.WaitAll(),Task.WaitAny(),Task.Result.不管那里出现了异常,最后抛出的就是一个System.AggregateException.
System.AggregateException时用来包装一个或者多个异常的,这个类时很有用的,特别是在调用Task.WaitAll()方法时。因为在Task.WaitAll()是等待多个task执行完成,如果有任意task执行出了异常,那么这个异常就会被记录在System.AggregateException中,不同的task可能抛出的异常不同,但是这些异常都会被记录下来。
下面就是给出一个例子:在例子中,创建了两个task,它们都抛出异常。然后主线程开始运行task,并且调用WaitAll()方法,然后就捕获抛出的System.AggregateException,显示详细信息。
代码
{
// create the tasks
Task task1 = new Task(() =>
{
ArgumentOutOfRangeException exception = new ArgumentOutOfRangeException();
exception.Source = "task1";
throw exception;
});
Task task2 = new Task(() =>
{
throw new NullReferenceException();
});
Task task3 = new Task(() =>
{
Console.WriteLine("Hello from Task 3");
});
// start the tasks
task1.Start(); task2.Start(); task3.Start();
// wait for all of the tasks to complete
// and wrap the method in a try...catch block
try
{
Task.WaitAll(task1, task2, task3);
}
catch (AggregateException ex)
{
// enumerate the exceptions that have been aggregated
foreach (Exception inner in ex.InnerExceptions)
{
Console.WriteLine("Exception type {0} from {1}",
inner.GetType(), inner.Source);
}
}
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
从上面的例子可以看出,为了获得被包装起来的异常,需要调用System.AggregateException的InnerExceptions属性,这个属性返回一个异常的集合,然后就可以遍历这个集合。
而且从上面的例子可以看到:Exeception.Source属性被用来指明task1的异常时ArgumentOutRangeException.
b.使用迭代的异常处理Handler
一般情况下,我们需要区分哪些异常需要处理,而哪些异常需要继续往上传递。AggregateException类提供了一个Handle()方法,我们可以用这个方法来处理
AggregateException中的每一个异常。在这个Handle()方法中,返回true就表明,这个异常我们已经处理了,不用抛出,反之。
在下面的例子中,抛出了一个OperationCancelException,在之前的task的取消一文中,已经提到过:当在task中抛出这个异常的时候,实际上就是这个task发送了取消的请求。下面的代码中,描述了如果在AggregateException.Handle()中处理不同的异常。
代码
// throw an exception to acknowledge the cancellation
throw new OperationCanceledException(token);
}, token);
// create a task that throws an exception
Task task2 = new Task(() =>
{
throw new NullReferenceException();
});
// start the tasks
task1.Start(); task2.Start();
// cancel the token
tokenSource.Cancel();
// wait on the tasks and catch any exceptions
try
{
Task.WaitAll(task1, task2);
}
catch (AggregateException ex)
{
// iterate through the inner exceptions using
// the handle method
ex.Handle((inner) =>
{
if (inner is OperationCanceledException)
{
// ...handle task cancellation...
return true;
}
else
{
// this is an exception we don't know how
// to handle, so return false
return false;
}
});
}
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
今天就写到这里。谢谢!
版权为小洋和博客园所有,转载请标明出处给作者。
http://www.cnblogs.com/yanyangtian
.NET 并行(多核)编程系列之五 Task执行和异常处理的更多相关文章
- .NET 并行(多核)编程系列之六 Task基础部分完结篇
原文:.NET 并行(多核)编程系列之六 Task基础部分完结篇 .NET 并行(多核)编程系列之六 Task基础部分完结篇 前言:之前的文章介绍了了并行编程的一些基本的,也注重的讲述了Task的一些 ...
- .NET 并行(多核)编程系列之七 共享数据问题和解决概述
原文:.NET 并行(多核)编程系列之七 共享数据问题和解决概述 .NET 并行(多核)编程系列之七 共享数据问题和解决概述 前言:之前的文章介绍了了并行编程的一些基础的知识,从本篇开始,将会讲述并行 ...
- .NET 4 并行(多核)编程系列之四 Task的休眠
原文:.NET 4 并行(多核)编程系列之四 Task的休眠 .NET 4 并行(多核)编程系列之四 Task的休眠 前言:之前的几篇文章断断续续的介绍了Task的一些功能:创建,取消.本篇介绍Tas ...
- paip.提升性能---并行多核编程哈的数据结构list,set,map
paip.提升性能---并行多核编程哈的数据结构list,set,map vector/copyonwritearraylist 都是线程安全的. 或者经过包装的list ::: collection ...
- Python编程系列---装饰器执行的底层原理及流程
代码中No.1 No.2 ...表示执行流程 """No.1 No.2 ...表示执行流程""" def set_func(func): ...
- .NET 4 并行(多核)编程系列之三 从Task的取消
原文:.NET 4 并行(多核)编程系列之三 从Task的取消 .NET 4 并行(多核)编程系列之三 从Task的取消 前言:因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编程 ...
- .NET 4 并行(多核)编程系列之二 从Task开始
原文:.NET 4 并行(多核)编程系列之二 从Task开始 .NET 4 并行(多核)编程系列之二 从Task开始 前言:我们一步步的从简单的开始讲述,还是沿用我一直的方式:慢慢演化,步步为营. ...
- [转].NET 4 并行(多核)编程系列之二 从Task开始
本文转自:http://www.cnblogs.com/yanyangtian/archive/2010/05/22/1741379.html .NET 4 并行(多核)编程系列之二 从Task开始 ...
- .NET 4 并行(多核)编程系列之一入门介绍
.NET 4 并行(多核)编程系列之一入门介绍 本系列文章将会对.NET 4中的并行编程技术(也称之为多核编程技术)以及应用作全面的介绍. 本篇文章的议题如下: 1. 并行编程和多线程编程的区别. ...
随机推荐
- Android入门之简单短信发送器
效果图: manifest.xml 文件中加入 <uses-permission android:name="android.permission.SEND_SMS"/&g ...
- 2014ACM/ICPC亚洲区西安站 F题 color (组合数学,容斥原理)
题目链接:传送门 题意: n个格子排成一行.我们有m种颜色.能够给这些格子涂色,保证相邻的格子的颜色不同 问,最后恰好使用了k种颜色的方案数. 分析: 看完题目描写叙述之后立刻想到了一个公式 :C(m ...
- 调用微信退款接口时,证书验证出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法
1.证书密码不正确,微信证书密码就是商户号 解决办法:请检查证书密码是不是和商户号一致 2.IIS设置错误,未加载用户配置文件 解决办法:找到网站使用的应用程序池-->右击-->高级设置- ...
- IntelliJ IDEA 14 注册码生成java代码(转)
https://confluence.jetbrains.com/display/IntelliJIDEA/Previous+IntelliJ+IDEA+Releases 分享几个license: ( ...
- (转)JAVA 调用Web Service的三种方法
1.使用HttpClient用到的jar文件:commons-httpclient-3.1.jar方法:预先定义好Soap请求数据,可以借助于XMLSpy Professional软件来做这一步生成. ...
- VS2010升级VS2013后,出现没有定义类型“PowerPacks.ShapeContainer”错误解决方法
开发说明: http://msdn.microsoft.com/zh-tw/library/microsoft.visualbasic.powerpacks.aspx Microsoft.Visual ...
- 推荐一套.NET文档处理组件Spire.Office
原文:推荐一套.NET文档处理组件Spire.Office 以前的项目中用到一点Word简单处理的功能(文字替换和转PDF格式),当时使用的是一套COM组件,必须在服务器上安装office环境.最近考 ...
- SVN的log,cat,list,diff的使用
svn log 展示给你主要信息:每个版本附加在版本上的作者与日期信息和所有路径修改. svn diff 显示特定修改的行级详细信息. svn cat ...
- NET通用平台
NET通用平台.通用权限.易扩展.多语言.多平台架构框架 先拿出我半前年前平台的设计初稿,经过半年的努力我已经完成了该设计稿的所有功能.并且理念已经远远超出该设计稿. 下面是一些博友对我贴子的评价: ...
- hadoop调度程序时出现“Error opening job jar”错误
提示出现的问题: Exception in thread "main" java.io.IOException: Error opening job jar: /home/depl ...