开发者社区> toyohu> 正文

.Net Framework 4.0 中利用Task实现并行处理、串并行混合处理

简介: 我们常常会遇到需要利用并行处理,尽量发挥多核或多CPU的潜能,提高程序运行效率的场景。在.NET环境下,常用的做法是使用Thread,多线程方式进行并行处理。但在.Net4.0中,微软提供一种新的概念——Task(任务),换句话说,并行处理由“多线程”进化为了“多任务”的方式。
+关注继续查看

    我们常常会遇到需要利用并行处理,尽量发挥多核或多CPU的潜能,提高程序运行效率的场景。在.NET环境下,常用的做法是使用Thread,多线程方式进行并行处理。但在.Net4.0中,微软提供一种新的概念——Task(任务),换句话说,并行处理由“多线程”进化为了“多任务”的方式。

 

一、利用Task实现多任务处理

测试1:

以下为测试过程,模拟多次调用一耗时方法,分别使用串行、多线程方式、多任务方式:

1、建立一虚拟耗时的方法

        /// <summary>
/// 模拟执行耗时的方法
/// </summary>
public static void TestLongTimeMethod()
{
Console.WriteLine("method start:" + System.DateTime.Now.ToString());
System.Threading.Thread.Sleep(5000);
Console.WriteLine("method end:" + System.DateTime.Now.ToString());
}

 

2、传统串行调用方式、多线程调用、多任务调用

        #region 传统串行方式
/// <summary>
/// 传统串行方式
/// </summary>
public static void lineMethod()
{
TestLongTimeMethod();
TestLongTimeMethod();
TestLongTimeMethod();
}
#endregion
        #region 多线程方式
/// <summary>
/// 多线程方式
/// </summary>
public static void threadMethod()
{
var thread1 = new Thread(() => TestLongTimeMethod());
var thread2 = new Thread(() => TestLongTimeMethod());
thread1.Start();
thread2.Start();
TestLongTimeMethod();
thread1.Join();
thread2.Join();
}
#endregion
        #region 多任务方式
/// <summary>
/// 多任务方式——线程池中,委托给CPU,全部执行完后再跳出线程池
/// </summary>
public static void taskMethod()
{
// 方式1:使用Parallel.Invoke,可同时并行多个任务,任务调用的方法可以不同
//Parallel.Invoke(
// () => TestLongTimeMethod(),
// () => TestLongTimeMethod(),
// () => TestLongTimeMethod()
//);

// 方式2:使用Parallel.For,可设定并行多个任务,任务调用的方法相同
int times = 3;
Parallel.For(
0,
times,
i => TestLongTimeMethod()
);
}
#endregion

3、模拟执行过程,统计过程用时

static void Main(string[] args)
{
int maxTimes = 1;
DateTime ds = new DateTime();
DateTime de = new DateTime();
DateTime ds1 = new DateTime();
DateTime de1 = new DateTime();
DateTime ds2 = new DateTime();
DateTime de2 = new DateTime();

#region lineMethod 串行

Console.WriteLine("**************【串 行】**************");
ds = DateTime.Now;
Console.WriteLine("**************[StartTime:" + ds.ToString() + "]**************");
for (int intLoop = 0; intLoop < maxTimes; intLoop++)
{
Console.WriteLine("**************[" + (intLoop + 1).ToString() + "]**************");
lineMethod();
}
de = DateTime.Now;
Console.WriteLine("**************[EndTime:" + de.ToString() + "]**************");
System.Threading.Thread.Sleep(500);

#endregion

#region threadMethod 多线程

Console.WriteLine("**************【多线程】**************");
ds1 = DateTime.Now;
Console.WriteLine("**************[StartTime:" + ds1.ToString() + "]**************");
for (int intLoop = 0; intLoop < maxTimes; intLoop++)
{
Console.WriteLine("**************[" + (intLoop + 1).ToString() + "]**************");
threadMethod();
}
de1 = DateTime.Now;
Console.WriteLine("**************[EndTime:" + de1.ToString() + "]**************");
System.Threading.Thread.Sleep(500);

#endregion

#region taskMethod 多任务

Console.WriteLine("**************【多任务】**************");
ds2 = DateTime.Now;
Console.WriteLine("**************[StartTime:" + ds2.ToString() + "]**************");
for (int intLoop = 0; intLoop < maxTimes; intLoop++)
{
Console.WriteLine("**************[" + (intLoop + 1).ToString() + "]**************");
taskMethod();
}
de2 = DateTime.Now;
Console.WriteLine("**************[EndTime:" + de2.ToString() + "]**************");
System.Threading.Thread.Sleep(500);

#endregion

Console.WriteLine("lineMethod 【串 行】 : " + (de - ds).TotalMilliseconds.ToString());
Console.WriteLine("threadMethod【多线程】 : " + (de1 - ds1).TotalMilliseconds.ToString());
Console.WriteLine("taskMethod 【多任务】 : " + (de2 - ds2).TotalMilliseconds.ToString());


Console.ReadLine();
}

4、执行结果截图

 

结论:从结果可以看出多线程或多任务的性能明显高于串行方式。多线程或多任务执行效率区别不大,.NET框架底层实现可能大致相同。但多任务的代码写法更为简洁,也更为灵活。

 

二、利用Task实现并行、串行的执行顺序定义

测试2::

1、假定A、B、C、D、E 多任务的执行顺序为:A、B 执行后,执行C,A 执行后,执行 D, B 执行后,执行 E
执行时的测试方法如下(即执行时显示执行的名称,并按传入的时间参数,决定进程休眠的时间):

    public class TestAction
{
private int _p;
private string _actionName;

public TestAction(string actionName, int p)
{
_actionName = actionName;
_p = p;
}

public void Do()
{
Console.WriteLine(System.DateTime.Now.ToString() + " | 开始执行" + _actionName);
Thread.Sleep(new TimeSpan(0, 0, _p));
Console.WriteLine(System.DateTime.Now.ToString() + " | 执行完毕" + _actionName);
}
}

2、测试方法(传统串行、串并行结合)

     假定各任务分别耗时为A(5秒)、B(5秒)、C(2秒)、D(1秒)、E(2秒)。则串行需用时5+5+2+1+2=15 秒,串并行结合(A、B -> C,A -> D,B -> E) 需用时 5+2 = 7 秒.

测试程序如下:

        /// <summary>
/// 按设计的顺序测试(同时考虑串行与并行): A、B -> C,A -> D,B -> E
/// </summary>
public static void SortTaskMethod()
{
Console.WriteLine("--------------[串行]--------------");
(new TestAction("A", 5)).Do();
(new TestAction("B", 5)).Do();
(new TestAction("C", 2)).Do();
(new TestAction("D", 1)).Do();
(new TestAction("E", 2)).Do();

Console.WriteLine("--------------[多任务]--------------");
TaskFactory factory = new TaskFactory();
Task a = factory.StartNew((new TestAction("A", 5)).Do);
Task b = factory.StartNew((new TestAction("B", 5)).Do);
Task c = factory.ContinueWhenAll(new Task[] { a, b }, ((preTasks) => (new TestAction("C", 2)).Do()));
Task d = factory.ContinueWhenAll(new Task[] { a }, ((preTasks) => (new TestAction("D", 1)).Do()));
Task e = factory.ContinueWhenAll(new Task[] { b }, ((preTasks) => (new TestAction("E", 2)).Do()));
}

3、执行结果截图

 

结论:与测试预想结果一致

实现的关键代码:

// 声明并获取一个Task工厂实例

TaskFactory factory = new TaskFactory();

// 利用工厂创建一个任务,并执行指定的方法

Task a = factory.StartNew((new TestAction("A", 5)).Do);

// 利用工厂创建后续任务(根据前置任务),并执行指定的方法

Task c = factory.ContinueWhenAll(new Task[] { a, b }, ((preTasks) => (new TestAction("C", 2)).Do()));


请注意以上使用工厂方式获得的任务实例,与之前介绍的Parallel.Invoke 方式,二者有很重要的区别:工厂方式获取任务实例后即分配给系统委托,不受当前调用的方法约束;但invoke方式,括号内部声明的多个任务,必须全部执行结束,才会跳出invoke,回到当前调用的方法中。




 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
netfilter源码学习(4)——NAT处理(1)
作者:gfree.wind@gmail.com 博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net    本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。
729 0
java.net.MalformedURLException: Local host name unknown报错处理
linux 修改host后启动tomcat报错 错误: 代理抛出异常错误: java.net.MalformedURLException: Local host name unknown: java.
2326 0
PreparedStatement批量处理的一个Framework(原创)
场景:批量进行DML操作,但涉及的表不同,不能使用executeBatch()需求:(1)如果DML中有一个错误时,要全部回滚;(2)如果全部正确,要全部执行;解决方案: package jdbc; import java.
1065 0
2017云栖大会·杭州峰会:《在线用户行为分析:基于流式计算的数据处理及应用》Workshop-入口
2017云栖大会·杭州峰会:《在线用户行为分析:基于流式计算的数据处理及应用》Workshop-入口
3223 0
Asp.Net Web API 2第七课——Web API异常处理
原文:Asp.Net Web API 2第七课——Web API异常处理 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.
863 0
hive executeTask被interrupt处理
异常信息如下: java.io.IOException: Failed on local exception: java.nio.channels.ClosedByInterruptException; Host Details : local host is: "hadoop008/192.
1199 0
Qt之处理QNetworkAccessManager网络连接超时
简述 在网络操作中,经常会由于各种原因引起网络连接超时,究竟何为网络连接超时? 网络连接超时:在程序默认的等待时间内没有得到服务器的响应 简述 超时原因 Qt 中的网络连接超时 如何处理超时 封装类 超时原因 引起网络连接超时的原因很多,下面,列举一些常见的原因: 网络断开,不过经常显示无法连接 网络阻塞,导致你不能在程序默认等待时间
4214 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
18474 0
+关注
toyohu
14年企业级软件及互联网产品研丰富发经验,曾任国内知名软件外包企业高级项目经理、手游公司技术总监。现任深圳前海童育汇电子商务股份有限公司产品研发负责人。
98
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载