.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,回到当前调用的方法中。




 

目录
相关文章
|
4月前
|
算法 Java 调度
|
6月前
|
关系型数据库 MySQL 数据库
找不到请求的 .Net Framework Data Provider。可能没有安装
做的一个项目,框架为.net framework 数据库为mysql 出现如标题错误 检查是否安装mysql、是否安装mysql connector net 笔者是因为没有安装后者mysql connector net 下载地址: [mysql connector net](https://downloads.mysql.com/archives/c-net/ "mysql connector net") 笔者安装截图如下: ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/c
60 0
【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。
【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。
666 0
【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。
|
6月前
|
C# Windows
[记录]c#.net framework 4.5调用运行时库
[记录]c#.net framework 4.5调用运行时库
|
1月前
|
Windows
windows server 2019 安装NET Framework 3.5失败,提示:“安装一个或多个角色、角色服务或功能失败” 解决方案
windows server 2019 安装NET Framework 3.5失败,提示:“安装一个或多个角色、角色服务或功能失败” 解决方案
100 0
|
6月前
|
Windows
​史上最详细的Windows10系统离线安装.NET Framework 3.5的方法(附离线安装包下载)
​史上最详细的Windows10系统离线安装.NET Framework 3.5的方法(附离线安装包下载)
565 0
|
4月前
|
C# Windows
C#安装“Windows 窗体应用(.NET Framework)”
C#安装“Windows 窗体应用(.NET Framework)”
51 0
|
7月前
|
开发框架 .NET 编译器
C#OOP之十四 .Net Framework简介
C#OOP之十四 .Net Framework简介
56 0
|
Windows
.Net Framework 0x800b0109 -已处理证书链,但是在不受信任提供程序信任的根证书中终止。
.Net Framework 0x800b0109 -已处理证书链,但是在不受信任提供程序信任的根证书中终止。
754 0
.Net Framework 0x800b0109 -已处理证书链,但是在不受信任提供程序信任的根证书中终止。
|
11月前
|
分布式计算 NoSQL Java
1..Net平台历程介绍和.net framework和netcore的架构体系对比,以及框架的选择介绍
1..Net平台历程介绍和.net framework和netcore的架构体系对比,以及框架的选择介绍
174 0