C# 并行开发总结

Posted Different life,the same belief

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 并行开发总结相关的知识,希望对你有一定的参考价值。

本文内容 均参考自 《C#并行高级编程》 

TPL 支持 数据并行(有大量数据要处理,必须对每个数据执行同样的操作, 任务并行(有好多可以并发运行的操作),流水线(任务并行和数据并行的结合体)

在.net 4.0 引入新的 Task Parallel Library 处理 并行开发 。 

Parallel类  

关键词   :  

Parallel.For   and Parallel.Foreach    -  负载均衡的多任务 

Parallel.Invoke                              -  并行运行多任务 

ParallelOptions                              -  指定最大并行度  (实例化一个类并修改MaxDegreeOfParallelism 属性的值 )    

Environment.ProcessorCount          -   内核最大数 

 

命令式任务并行 

关键词 : Task类 , 一个task 类表示一个异步操作 (需要考虑到任务的开销)  

启动任务使用Task类的Start  方法 ,  等待线程完成使用WaitAll 方法 ,  通过CancellationTokenSource 的Cancel方法来 中断 Task的运行 

怎样表达任务间的父子关系 ?   TaskCreationOption的AttachToParent来完成 

怎样来表达串行任务 ? Task.ContinueWith

 

 

并发集合 

BlockingCollection 

ConcurrentDictionary/ConcurrentQueue/ConcurrentStack

 

下面来一个例子是实操 C# 多任务并发。

场景 :  主进程 打开 一个 生产者线程 和 一个消费线程 。 他们之间可以相互对话, 如([动词,名词]) say,hello  task,a  .   生产者说一句话 消费者听, 消费者或应答或提交新的任务或结束自己。  

代码 

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace TPLTest
{
	class Program
	{
		public static readonly int MAX_DATA_LENGTH         =  256; 
		private static BlockingCollection<Message> bcstr   = new BlockingCollection<Message>(MAX_DATA_LENGTH) ;
		public static readonly string SAY_THANKS           = "thanks";
		public static readonly string SAY_WELCOME          = "welcome!";
		public static readonly string BYE                  = "bye";
		public static readonly string SAY                  = "say";
		public static readonly string TASK                 = "task";
		public static readonly string TIMEOUT              = "timeout";
		public static readonly string ONLINE               = "ONLINE";
		public static readonly string WHAT                 = "What?";
		public static readonly int    WAIT                 = 20000;
		public static void Main(string[] args)
		{
			
			//消费者线程  
			ParallelOptions po = new ParallelOptions();
			po.MaxDegreeOfParallelism = -1; 
			Parallel.Invoke(po,() => {
				int selfID = Environment.CurrentManagedThreadId;
				Message customer = new Message();
				customer.CustomerThreadID = selfID ;
				customer.content = ONLINE;
				Console.WriteLine(customer.ToString(false));
				while(true){
					if (bcstr.TryTake(out customer, WAIT))
					{
					    customer.CustomerThreadID = selfID ;
					    customer.doAction();
					    Console.WriteLine(" ");
					    Console.WriteLine(customer.ToString(false));
						if (customer.endThread()){
					    	break;
					    } 
					     
					} else {
						if (customer == null)
						{
							customer = new Message();
						}
					    customer.CustomerThreadID = selfID ;
					    customer.content  =  TIMEOUT;   
					    Console.WriteLine(customer.ToString(false));
					}
				}
			}, 
			() => {
				int prdID = Environment.CurrentManagedThreadId;
				Message productor  = new Message(); 
				productor.ProductorThreadID = prdID; 
				productor.content           = ONLINE;
				Console.WriteLine(productor.ToString(true));
				while(true){
					Console.Write("Productor Behavior (i.e. say,hello) :   ");
					string msgContent = Console.ReadLine();
					productor       = new Message(); 
					productor.ProductorThreadID = prdID; 
					productor.key   = msgContent.Split(‘,‘)[0];
					productor.content = msgContent.Split(‘,‘)[1]; 
					bcstr.Add(productor);
					if (productor.endThread()) {
						break;
					}
				}
			});
			
			
			
		}
	}
	
	class Message
	{
		public int    ProductorThreadID {get; set;}
		public int    CustomerThreadID  {get; set;}
		public string key {get; set;}
		public string content{get; set;}
		public bool   endThread()
		{
			return string.Compare(key, Program.BYE) == 0;
		}
		
		public string ToString(bool isProductor){
			return string.Format("{0} Thread ID {1} : {2}", isProductor ? "Productor" : "Customer",  
			                                                isProductor ?  ProductorThreadID.ToString() : CustomerThreadID.ToString(), 
			                                                content);
		}
		
		public void doAction(){
			if (string.Compare(key, Program.SAY) == 0) {
				content = string.Compare(content, Program.SAY_THANKS) == 0 ?  Program.SAY_WELCOME : Program.WHAT;
			}
			
			if (string.Compare(key, Program.TASK) == 0) {
				Task taskA = Task.Factory.StartNew(() => {
				    Console.WriteLine("task A begin ");
				    Task ChildOfFatehrA = Task.Factory.StartNew(() => {
				     	Console.WriteLine("Sub task A begin ");
				    	Thread.Sleep(1000);
				    	Console.WriteLine("Sub task A end ");                          	
					});
				    ChildOfFatehrA.Wait();
				    Console.WriteLine("task A end ");
				    
				});
				taskA.ContinueWith(taskB => {
					Console.WriteLine("task B begin ");
				    Thread.Sleep(5000);
				    Console.WriteLine("task B end ");                     
				});
				taskA.Wait(); 
			}
		}
			
	}
}

  

 

以上是关于C# 并行开发总结的主要内容,如果未能解决你的问题,请参考以下文章

Sleep() 方法后的代码片段没有被执行

如何在 python 中并行化以下代码片段?

C#程序员经常用到的10个实用代码片段 - 操作系统

Golang与C#之switch区别

Java 和 C# 的并行开发

[工作积累] UE4 并行渲染的同步 - Sync between FParallelCommandListSet & FRHICommandListImmediate calls(代码片段