[C#]『Parallel.For』『Parallel.ForEach』任务并行库使用小计

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

Parallel 类提供对并行循环和区域的支持。

许多个人计算机和工作站都有两个或四个内核(即 CPU),使多个线程能够同时执行。 在不久的将来,计算机预期会有更多的内核。 为了利用当今和未来的硬件,您可以对代码进行并行化,以将工作分摊在多个处理器上。 过去,并行化需要线程和锁的低级操作。 Visual Studio 2010 和 .NET Framework 4 提供了新的运行时、新的类库类型以及新的诊断工具,从而增强了对并行编程的支持。 这些功能简化了并行开发,使您能够通过固有方法编写高效、细化且可伸缩的并行代码,而不必直接处理线程或线程池。 下图从较高层面上概述了 .NET Framework 4 中的并行编程体系结构。

上面是MSDN对于并行任务的解释,简而言之就是同时执行多个任务,带来效率上的提高,但是同时带来CPU占用;

 

1.简单Parallel.For/Parallel.ForEach循环

usingSystem;

usingSystem.Diagnostics;

usingSystem.Threading;

usingSystem.Threading.Tasks;

 

namespaceConsoleapplication17

{

classPRogram

{

staticvoidMain(string[] args)

{

try

{

NormalFor();

ParallelFor();

}

catch(Exception ex)

{

Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));

}

finally

{

Console.ReadLine();

}

}

staticint_forCount = 100;

staticvoidNormalFor()

{

Stopwatch _watch =newStopwatch();

_watch.Start();

for(inti = 0; i < _forCount; i++)

{

DoSomeWork(i);

}

_watch.Stop();

Console.WriteLine(string.Format("Normal For Cost Time:{0}", _watch.ElapsedMilliseconds));

}

staticvoidParallelFor()

{

Stopwatch _watch =newStopwatch();

_watch.Start();

//写法一

Parallel.For(0, _forCount, i =>

{

DoSomeWork(i);

});

_watch.Stop();

Console.WriteLine(string.Format("Parallel For Cost Time:{0}", _watch.ElapsedMilliseconds));

/*

Parallel.For(0, _forCount, DoSomeWork);//写法二

Parallel.For(0, _forCount, (int i) => { DoSomeWork(i); });//写法三

*/

}

staticvoidDoSomeWork(inti)

{

if(i < 0)

thrownewArgumentException("i");

Thread.Sleep(100);

}

}

}

.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, "Courier New", courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp{ background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, "Courier New", courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }代码效果

2.停止或中断 Parallel.For 循环usingSystem;

usingSystem.Diagnostics;

usingSystem.Threading;

usingSystem.Threading.Tasks;

 

namespaceConsoleApplication17

{

classProgram

{

staticvoidMain(string[] args)

{

try

{

BreakParallelFor();

}

catch(Exception ex)

{

Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));

}

finally

{

Console.ReadLine();

}

}

staticint_forCount = 100;

staticvoid

BreakParallelFor()

{

Parallel.For(0, _forCount, (i, status) =>

{

if(i == 22)

{

Console.WriteLine("Parallel For Break....");

status.Break();

}

Console.WriteLine(string.Format("output :{0}", i));

Thread.Sleep(100);

});

}

}

}

.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, "Courier New", courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }代码效果

看看MSDN关于此的解释:

在 ParallelFor() 或 [Overload:System.Threading.Tasks.Parallel.Parallel.ForEach`1] 循环中,不能使用与顺序循环中相同的 break 或 Exit 语句,这是因为这些语言构造对于循环是有效的,而并行“循环”实际上是方法,不是循环。 相反,可以使用 Stop 或 Break 方法。 Parallel.For的一些重载接受 Action<int, ParallelLoopState>(在 Visual Basic 中为 Action(Of Integer, ParallelLoopState))作为输入参数。 ParallelLoopState 对象由运行时在后台创建,您可以在 lambda 表达式中为它指定您喜欢的任何名称。

在调用 Stop 或 Break 后,循环中的其他线程可能会继续运行一段时间(这不受应用程序开发人员的控制),理解这一点很重要。可以使用 ParallelLoopState.IsStopped 属性检查是否已在另一个线程上停止该循环。

理解黄色标注地方很重要;

 

3.具有线程局部变量的 Parallel.ForEach Parallel.For 循环

usingSystem;usingSystem.Linq;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceConsoleApplication17

{classProgram

{staticvoidMain(string[] args)

{try{//例子参考自MSDN:http://msdn.microsoft.com/zh-cn/library/dd460703%28v=vs.100%29.aspxint[] _nums = Enumerable.Range(0, 10).ToArray();long_fortotal = 0, _foreahtotal = 0;

Parallel.For<long>(0, _nums.Length,

() => 0,//每次遍历开始时候初始化变量 类似于 int _subSum=0;(i, loopStatus, eachLoopTotal) =>//i:循环的索引;loopstatus:并行遍历状态;eachLoopTotal:每次遍历累加小计值{

eachLoopTotal += _nums[i];returneachLoopTotal;

},

(eachLoopTotal) =>//遍历结束时候,将上面每次累加小计数值传递过来,进行总的累加{

Interlocked.Add(ref_fortotal, eachLoopTotal);

});/*localInit类型:System.Func<TLocal>用于返回每个线程的本地数据的初始状态的函数委托。body类型:System.Func<Int64, ParallelLoopState, TLocal, TLocal>将为每个迭代调用一次的委托。localFinally类型:System.Action<TLocal>用于对每个线程的本地状态执行一个最终操作的委托。*/Parallel.ForEach<int,long>(_nums,

() => 0,

(i, loopStatus, eachLoopTotal) =>

{

eachLoopTotal += _nums[i];returneachLoopTotal;

},

(eachLoopTotal) =>

{

Interlocked.Add(ref_foreahtotal, eachLoopTotal);

});

Console.WriteLine("The Parallel.For is {0}", _fortotal);

Console.WriteLine("The Parallel.ForEach is {0}", _foreahtotal);

}catch(Exception ex)

{

Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));

}finally{

Console.ReadLine();

}

}

}

}

 

.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, "Courier New", courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }代码效果

 

4.取消 Parallel.For/ForEach Loop

usingSystem;

usingSystem.Threading;

usingSystem.Threading.Tasks;

 

namespaceConsoleApplication17

{

classProgram

{

staticvoidMain(string[] args)

{

try

{

/*

CancellationToken 获取或设置与此 ParallelOptions 实例关联的 CancellationToken。

MaxDegreeOfParallelism 获取或设置此 ParallelOptions 实例所允许的最大并行度。

TaskScheduler 获取或设置与此 ParallelOptions 实例关联的 TaskScheduler。 将此属性设置为 null,以指示应使用当前计划程序。

MaxDegreeOfParallelism MaxDegreeOfParallelism设置为2,表示最多可以有2个并行量(可以理解成并行线程数目),如果设置为为 -1,表示对于应该使用的并行量没有上限设置。如果将其设置为1,则效果和单线程一样.

*/

CancellationTokenSource _cancel =newCancellationTokenSource();

ParallelOptions _po =newParallelOptions();

_po.CancellationToken = _cancel.Token;

_po.MaxDegreeOfParallelism = Environment.ProcessorCount;

 

Parallel.For(0, 100, _po, i =>

{

if(i == 22)

_cancel.Cancel();

Console.WriteLine(string.Format("output {0}", i));

});

}

catch(OperationCanceledException e)

{

Console.WriteLine(e.Message);

}

catch(Exception ex)

{

Console.WriteLine(string.Format("Exception Message:{0}", ex.Message.Trim()));

}

finally

{

Console.ReadLine();

}

}

}

}

.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, "Courier New", courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }代码效果

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航