C#中怎么实现并行编程
C#中怎么实现并行编程,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
并行的相关实战
说到并行,就需要先说下.NET FX4中引入的Task Parallel Library(任务并行库),简称TPL。TPL主要覆盖了三大使用场景,数据并行、任务并行和流水线,TPL以其高度的封装特性,隐藏了并行编程里复杂的处理,使得开发人员可以以较低的门槛进行并行编程。
数据并行
这种场景在于有大量数据需要处理,而且对每一份数据都要执行的同样的操作。
任务并行
有很多相对独立的不同操作,或者可以分割成多个子任务但彼此之间是独立的,就可以通过任务并行来发挥并行化的优势
流水线
流水线是以上两种场景的结合,这个也是最复杂最难处理的场景,因为这里面涉及到多个并发的任务进行协调处理。
此场景,奈何小编理解的不是很好,所以不敢乱写,多方查找资料,找到了oschina上的一篇文章。
流水线技术,指的是允许一个机器周期内的计算机各处理步骤重叠进行。特别是,当执行一条指令时,可以读取下一条指令,也就意味着,在任何一个时刻可以有不止一条指令在"流水线"上,每条指令处在不同的执行阶段。这样,即便读取和执行每条指令的时间保持不变,而计算机的总的吞吐量提高了。
原文地址:https://my.oschina.net/u/3374461/blog/1930305
System.Threading.Tasks.Parallel类
虽然Parallel类在System.Threading.Tasks命名空间下,但是创建并行代码不一定要直接使用Task类的实例,我们可以直接使用Parallel静态类所提供的方法。
Parallel.For:为固定数目的独立For循环迭代提供了负载均衡式的并行执行
Parallel.For(0, 5, i =>{ Console.WriteLine("the number is", i);});
Parallel.Foreach:为固定数目的独立ForEach循环迭代提供了负载均衡式的并行执行。这个方法支持自定义分区器(Partitioner),以使得我们可以完全掌控数据分发。
string[] letters = new string[] {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"};Parallel.ForEach(letters, i => Console.WriteLine("letter is " + i));
Parallel.Invoke:为给定的独立任务提供了负载均衡式的并行执行,接下来会重点讨论这个方法。
Parallel.Invoke
这个方法很实用,也很简单。
以下代码可以返回void的无参数方法:
Parallel.Invoke(Method1(), Method2(), Method3(), Method4());
通过Lambda表达式运行:
Parallel.Invoke(() => Method1(), () => Method2(), () => Method3(), () => Method4());
通过Lambda表达式和匿名类型来运行:
Parallel.Invoke(() =>{ Method1(); // Do something}, () =>{ Method2(); // Do something }, () => { Method3(); // Do something }, () => { Method4(); // Do something});
以上代码需要并行执行四个方法,但是如果空余逻辑内核不足四个或者根本就没有四个逻辑内核,这四个方法是不能并发执行的。因此在理想情况下,正好有至少四个空余逻辑内核时,我们就可以并行执行这四个方法了。
这四个方法,我们无法准确的预测其执行顺序,因为这一切是由底层的逻辑会根据运行时的现有可用资源创建出最合适的执行计划。当然TPL依然有机制保证方法的顺序执行,这个以后我们再讨论。
Parallel.Invoke最大的优势就是简单,但是并不能因为它简单,就不分场合的使用,事实上,我们需要在某些场景下权衡使用。
如果这四个方法的执行时间不一致,那么就需要根据最长的执行时间才能返回控制,这就可能造成一些逻辑内核处于闲置状态。所以我们需要预测一下大致的执行时间,如果时间过长,那么就要认真考虑是否真的需要使用这个方法。
其扩展性很差,因为它只能调用固定数目的逻辑内核,剩余内核就会一直处于闲置状态。
方法之间的交互极其困难,极易产生Bug,当然这是并行编程的常见问题,TPL也考虑到了这点,也有足够机制解决这个问题。
如果其中某个方法有了异常,捕捉异常会很困难,所以需要大家在相应的被调用方法里编写足够的日志。
小编在以前的使用中还遇到了内存溢出的异常,这些也会在以后的文章中说明其原因以及解决方法。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。