.Net Framework 4.0 中利用Task实现并行处理、串并行混合处理
??? 我們常常會(huì)遇到需要利用并行處理,盡量發(fā)揮多核或多CPU的潛能,提高程序運(yùn)行效率的場(chǎng)景。在.NET環(huán)境下,常用的做法是使用Thread,多線程方式進(jìn)行并行處理。但在.Net4.0中,微軟提供一種新的概念——Task(任務(wù)),換句話說(shuō),并行處理由“多線程”進(jìn)化為了“多任務(wù)”的方式。
?
一、利用Task實(shí)現(xiàn)多任務(wù)處理
測(cè)試1:
以下為測(cè)試過(guò)程,模擬多次調(diào)用一耗時(shí)方法,分別使用串行、多線程方式、多任務(wù)方式:
1、建立一虛擬耗時(shí)的方法
/// <summary>/// 模擬執(zhí)行耗時(shí)的方法
/// </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、傳統(tǒng)串行調(diào)用方式、多線程調(diào)用、多任務(wù)調(diào)用
#region 傳統(tǒng)串行方式/// <summary>
/// 傳統(tǒng)串行方式
/// </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 多任務(wù)方式
/// <summary>
/// 多任務(wù)方式——線程池中,委托給CPU,全部執(zhí)行完后再跳出線程池
/// </summary>
public static void taskMethod()
{
// 方式1:使用Parallel.Invoke,可同時(shí)并行多個(gè)任務(wù),任務(wù)調(diào)用的方法可以不同
//Parallel.Invoke(
// () => TestLongTimeMethod(),
// () => TestLongTimeMethod(),
// () => TestLongTimeMethod()
//);
// 方式2:使用Parallel.For,可設(shè)定并行多個(gè)任務(wù),任務(wù)調(diào)用的方法相同
int times = 3;
Parallel.For(
0,
times,
i => TestLongTimeMethod()
);
}
#endregion
3、模擬執(zhí)行過(guò)程,統(tǒng)計(jì)過(guò)程用時(shí)
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 多任務(wù)
Console.WriteLine("**************【多任務(wù)】**************");
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 【多任務(wù)】 : " + (de2 - ds2).TotalMilliseconds.ToString());
Console.ReadLine();
}
4、執(zhí)行結(jié)果截圖
?
結(jié)論:從結(jié)果可以看出多線程或多任務(wù)的性能明顯高于串行方式。多線程或多任務(wù)執(zhí)行效率區(qū)別不大,.NET框架底層實(shí)現(xiàn)可能大致相同。但多任務(wù)的代碼寫(xiě)法更為簡(jiǎn)潔,也更為靈活。
?
二、利用Task實(shí)現(xiàn)并行、串行的執(zhí)行順序定義
測(cè)試2::
1、假定A、B、C、D、E 多任務(wù)的執(zhí)行順序?yàn)?#xff1a;A、B 執(zhí)行后,執(zhí)行C,A?執(zhí)行后,執(zhí)行 D, B?執(zhí)行后,執(zhí)行 E
執(zhí)行時(shí)的測(cè)試方法如下(即執(zhí)行時(shí)顯示執(zhí)行的名稱,并按傳入的時(shí)間參數(shù),決定進(jìn)程休眠的時(shí)間):
{
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() + " | 開(kāi)始執(zhí)行" + _actionName);
Thread.Sleep(new TimeSpan(0, 0, _p));
Console.WriteLine(System.DateTime.Now.ToString() + " | 執(zhí)行完畢" + _actionName);
}
}
2、測(cè)試方法(傳統(tǒng)串行、串并行結(jié)合)
???? 假定各任務(wù)分別耗時(shí)為A(5秒)、B(5秒)、C(2秒)、D(1秒)、E(2秒)。則串行需用時(shí)5+5+2+1+2=15 秒,串并行結(jié)合(A、B -> C,A -> D,B -> E) 需用時(shí) 5+2 = 7 秒.
測(cè)試程序如下:
/// <summary>/// 按設(shè)計(jì)的順序測(cè)試(同時(shí)考慮串行與并行): 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("--------------[多任務(wù)]--------------");
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、執(zhí)行結(jié)果截圖
?
結(jié)論:與測(cè)試預(yù)想結(jié)果一致
實(shí)現(xiàn)的關(guān)鍵代碼:
// 聲明并獲取一個(gè)Task工廠實(shí)例TaskFactory factory = new TaskFactory();
// 利用工廠創(chuàng)建一個(gè)任務(wù),并執(zhí)行指定的方法
Task a = factory.StartNew((new TestAction("A", 5)).Do);
// 利用工廠創(chuàng)建后續(xù)任務(wù)(根據(jù)前置任務(wù)),并執(zhí)行指定的方法
Task c = factory.ContinueWhenAll(new Task[] { a, b }, ((preTasks) => (new TestAction("C", 2)).Do()));
請(qǐng)注意以上使用工廠方式獲得的任務(wù)實(shí)例,與之前介紹的Parallel.Invoke 方式,二者有很重要的區(qū)別:工廠方式獲取任務(wù)實(shí)例后即分配給系統(tǒng)委托,不受當(dāng)前調(diào)用的方法約束;但invoke方式,括號(hào)內(nèi)部聲明的多個(gè)任務(wù),必須全部執(zhí)行結(jié)束,才會(huì)跳出invoke,回到當(dāng)前調(diào)用的方法中。
?
總結(jié)
以上是生活随笔為你收集整理的.Net Framework 4.0 中利用Task实现并行处理、串并行混合处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Code-First Migration
- 下一篇: 《深入Python》-11. HTTP