Parallel

mac2022-06-30  46

介绍 C# 4.0 的新特性之并行运算

Parallel.For - for 循环的并行运算 Parallel.ForEach - foreach 循环的并行运算 Parallel.Invoke - 并行调用多个任务 Task - 任务,基于线程池。其使我们对并行编程变得更简单,且不用关心底层是怎么实现的PLINQ - 用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算

示例 1、Parallel.For 的 Demo Parallel/ParallelFor.aspx.cs

代码 using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace CSharp.Parallel {     public partial class ParallelFor : System.Web.UI.Page     {         protected void Page_Load(object sender, EventArgs e)         {             Normal();             ParallelForDemo();         }         private void Normal()         {             DateTime dt = DateTime.Now;             for (int i = 0; i < 20; i++)             {                 GetData(i);             }             Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());             Response.Write("<br />");             Response.Write("<br />");         }         private void ParallelForDemo()         {             DateTime dt = DateTime.Now;             // System.Threading.Tasks.Parallel.For - for 循环的并行运算            System.Threading.Tasks.Parallel.For(020, (i) => { GetData(i); });             Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());             Response.Write("<br />");         }         private int GetData(int i)         {             System.Threading.Thread.Sleep(100);             Response.Write(i.ToString());             Response.Write("<br />");             return i;         }     } }/* 运行结果: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 2000.0514 0 13 1 19 7 12 18 6 2 8 10 14 4 16 5 3 15 17 9 11 300.0077*/

2、Parallel.ForEach 的 Demo Parallel/ParallelForEach.aspx.cs

代码 using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace CSharp.Parallel {     public partial class ParallelForEach : System.Web.UI.Page     {         private List<int> _data = new List<int>();         protected void Page_Load(object sender, EventArgs e)         {             InitData();             Normal();             ParallelForEachDemo();         }         private void InitData()         {             _data.Clear();             for (int i = 0; i < 20; i++)             {                 _data.Add(i);             }         }         private void Normal()         {             DateTime dt = DateTime.Now;             for (int i = 0; i < 20; i++)             {                 GetData(i);             }             Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());             Response.Write("<br />");             Response.Write("<br />");         }         private void ParallelForEachDemo()         {             DateTime dt = DateTime.Now;             // System.Threading.Tasks.Parallel.ForEach - foreach 循环的并行运算            System.Threading.Tasks.Parallel.ForEach(_data, (index) => { GetData(index); });             Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());             Response.Write("<br />");         }         private int GetData(int i)         {             System.Threading.Thread.Sleep(100);             Response.Write(i.ToString());             Response.Write("<br />");             return i;         }     } }/* 运行结果: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 2000.0514 0 6 12 18 1 2 7 13 19 4 3 8 14 9 5 15 10 16 11 17 600.0154*/

3、Parallel.Invoke 的 Demo Parallel/ParallelInvoke.aspx.cs

代码 using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Threading;namespace CSharp.Parallel {     public partial class ParallelInvoke : System.Web.UI.Page     {         protected void Page_Load(object sender, EventArgs e)         {             var tasks = new Action[] { () => Task1(), () => Task2(), () => Task3() };             // System.Threading.Tasks.Parallel.Invoke - 并行调用多个任务            System.Threading.Tasks.Parallel.Invoke(tasks);         }         private void Task1()         {             Thread.Sleep(3000);             Response.Write("Task1 - " + "ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"));             Response.Write("<br />");         }         private void Task2()         {             System.Threading.Thread.Sleep(3000);             Response.Write("Task2 - " + "ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"));             Response.Write("<br />");         }         private void Task3()         {             System.Threading.Thread.Sleep(3000);             Response.Write("Task3 - " + "ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() + " - " + DateTime.Now.ToString("HH:mm:ss"));             Response.Write("<br />");         }     } }/* 运行结果: Task2 - ThreadId:26 - 09:11:58 Task1 - ThreadId:25 - 09:11:58 Task3 - ThreadId:24 - 09:11:58*/

4、Task 的 Demo Parallel/ParallelTask.aspx.cs

代码 /* Task - 任务,基于线程池。其使我们对并行编程变得更简单,且不用关心底层是怎么实现的*/using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Threading;using System.Threading.Tasks;namespace CSharp.Parallel {        public partial class ParallelTask : System.Web.UI.Page     {         protected void Page_Load(object sender, EventArgs e)         {             /*              * CancellationTokenSource - 取消任务的操作需要用到的一个类              *     Token - 一个 CancellationToken 类型的对象,用于通知取消指定的操作              *     IsCancellationRequested - 是否收到了取消操作的请求              *     Cancel() - 结束任务的执行              * ParallelOptions - 并行运算选项              *     CancellationToken - 设置一个 Token,用于取消任务时的相关操作              *     MaxDegreeOfParallelism - 指定一个并行循环最多可以使用多少个线程              */             CancellationTokenSource cts = new CancellationTokenSource();             ParallelOptions pOption = new ParallelOptions() { CancellationToken = cts.Token };             pOption.MaxDegreeOfParallelism = 10;             Response.Write("开始执行,3.5 秒后结束");             Response.Write("<br />");             /*              * Task - 任务类              *     Factory.StartNew() - 创建并开始一个或一批新任务              *     ContinueWith() - 此任务完成后执行指定的另一个任务              *     AsyncState - 此任务的上下文对象              *     Wait() - 阻塞,直到任务完成              */             Task task0 = Task.Factory.StartNew(() =>             {                 Thread.Sleep(3500);                 cts.Cancel();                 Response.Write("结束");                 Response.Write("<br />");             });             // 通过 System.Threading.Tasks.Parallel.Invoke 执行任务的时候,可以加入 ParallelOptions 参数,用于对此并行运算做一些配置            System.Threading.Tasks.Parallel.Invoke(pOption,                 () => Task1(pOption.CancellationToken),                 () => Task2(pOption.CancellationToken));             /*              * 一个 Task 内可以包含多个 Task             Task tasks = new Task(() =>              {                 Task.Factory.StartNew(() => Method());                  Task.Factory.StartNew(() => Method2());                  Task.Factory.StartNew(() => Method3());              });              tasks.Start();              // 阻塞,直到整个任务完成             tasks.Wait();              */             /*              * 带返回值的 Task             Func<object, long> fun = delegate(object state)             {                 return 1.0;             };             Task<long> tsk = new Task<long>(fun, "state");             tsk.Start();             Response.Write(tsk.Result.ToString());              */         }                 private void Task1(CancellationToken token)         {             // 每隔 1 秒执行一次,直到此任务收到了取消的请求             // 注意:虽然此处是其他线程要向主线程(UI线程)上输出信息,但因为使用了 Task ,所以不用做任何处理            while (!token.IsCancellationRequested)             {                 Response.Write("Task1 - " + "ThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString());                 Response.Write("<br />");                 Thread.Sleep(1000);             }         }         private void Task2(CancellationToken token)         {             while (!token.IsCancellationRequested)             {                 Response.Write("Task2 - " + "ThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString());                 Response.Write("<br />");                 Thread.Sleep(1000);             }         }     } }/* 运行结果: 开始执行,3.5 秒后结束 Task2 - ThreadId: 6 Task1 - ThreadId: 48 Task1 - ThreadId: 48 Task2 - ThreadId: 6 Task2 - ThreadId: 6 Task1 - ThreadId: 48 Task2 - ThreadId: 6 Task1 - ThreadId: 48 结束*/

5、PLINQ 的 Demo Parallel/ParallelPLINQ.aspx.cs

代码 /* PLINQ - 用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算*/using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace CSharp.Parallel {     public partial class ParallelPLINQ : System.Web.UI.Page     {         protected void Page_Load(object sender, EventArgs e)         {             List<int> list = new List<int>();             for (int i = 0; i < 100; i++)             {                 list.Add(i);             }             // AsParallel() - 并行运算             // AsSequential() - 串行运算             // AsOrdered() - 保持数据的原有顺序(AsSequential()指的是串行运算;AsOrdered()指的是如果在并行运算的前提下,它会把结果先缓存,然后排序,最后再把排序后的数据做输出)             // AsUnordered() - 可以不必保持数据的原有顺序             // WithDegreeOfParallelism() - 明确地指出需要使用多少个线程来完成工作             // WithCancellation(new CancellationTokenSource().Token) - 指定一个 CancellationToken 类型的参数             ParallelQuery nums = from num in list.AsParallel<int>().AsOrdered<int>()                                  where num % 10 == 0                                  select num;             foreach (var num in nums)             {                 Response.Write(num.ToString());                 Response.Write("<br />");             }             // 聚合方法也可以做并行运算            Response.Write(list.AsParallel().Average().ToString());             Response.Write("<br />");             // 自定义聚合方法做并行运算的 Demo(实现一个取集合的平均值的功能)            double myAggregateResult = list.AsParallel().Aggregate(                 // 聚合变量的初始值                0d,                    // 在每个数据分区上,计算此分区上的数据                 // 第一个参数:对应的数据分区的计算结果;第二个参数:对应的数据分区的每个数据项                (value, item) =>                  {                     double result = value + item;                     return result;                  },                 // 根据每个数据分区上的计算结果,再次做计算                 // 第一个参数:全部数据的计算结果;第二个参数:每个数据分区上的计算结果                (value, data) =>                 {                     double result = value + data;                     return result;                 },                 // 根据全部数据的计算结果再次计算,得到最终的聚合结果                (result) => result / list.Count             );             Response.Write(myAggregateResult.ToString());         }      } }/* 运行结果: 0 10 20 30 40 50 60 70 80 90 49.5 49.5 */

注:关于并行运算的实例可以参考http://code.msdn.microsoft.com/ParExtSamples

转载于:https://www.cnblogs.com/zhangyu1024/p/5198795.html

相关资源:Parallel Computer Architecture - A Hardware Software Approach
最新回复(0)