精进不休 .NET 4.0 (5) - C# 4.0 新特性之并行运算(Parallel)

简介:
[索引页]
[源码下载]


精进不休 .NET 4.0 (5) - C# 4.0 新特性之并行运算(Parallel)


作者: webabcd


介绍
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 
        { 
void Page_Load() void Page_Load(object sender, EventArgs e) 
                { 
                        Normal(); 
                        ParallelForDemo(); 
                } 

void Normal() 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 />"); 
                } 

void ParallelForDemo() void ParallelForDemo() 
                { 
                        DateTime dt = DateTime.Now; 

                        // System.Threading.Tasks.Parallel. For -  for 循环的并行运算 
                        System.Threading.Tasks.Parallel. For(0, 20, (i) => { GetData(i); }); 

                        Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString()); 
                        Response.Write( "<br />"); 
                } 

int GetData() int GetData(int i) 
                { 
                        System.Threading.Thread.Sleep(100); 
                        Response.Write(i.ToString()); 
                        Response.Write( "<br />"); 
                        return i; 
                } 
        } 


/* 
运行结果: 










10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
2000.0514 


13 

19 

12 
18 



10 
14 

16 


15 
17 

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 
        { 
List<int> _data =  new List<int>() List<int> _data =  new List<int>(); 

void Page_Load() void Page_Load(object sender, EventArgs e) 
                { 
                        InitData(); 

                        Normal(); 
                        ParallelForEachDemo(); 
                } 

void InitData() void InitData() 
                { 
                        _data.Clear(); 
                         for (int i = 0; i < 20; i++) 
                        { 
                                _data.Add(i); 
                        } 
                } 

void Normal() 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 />"); 
                } 

void ParallelForEachDemo() 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 />"); 
                } 

int GetData() int GetData(int i) 
                { 
                        System.Threading.Thread.Sleep(100); 
                        Response.Write(i.ToString()); 
                        Response.Write( "<br />"); 
                        return i; 
                } 
        } 


/* 
运行结果: 










10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
2000.0514 



12 
18 



13 
19 



14 


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 
        { 
void Page_Load() 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); 
                } 

void Task1() void Task1() 
                { 
                        Thread.Sleep(3000); 
                        Response.Write( "Task1 - " +  "ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() +  " - "+ DateTime.Now.ToString( "HH:mm:ss")); 
                        Response.Write( "<br />"); 
                } 

void Task2() void Task2() 
                { 
                        System.Threading.Thread.Sleep(3000); 
                        Response.Write( "Task2 - " +  "ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() +  " - "+ DateTime.Now.ToString( "HH:mm:ss")); 
                        Response.Write( "<br />"); 
                } 

void Task3() 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 
        { 
void Page_Load() 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());    
                        */ 
                } 
                
void Task1() void Task1(CancellationToken token) 
                { 
                        // 每隔 1 秒执行一次,直到此任务收到了取消的请求 
                        // 注意:虽然此处是其他线程要向主线程(UI线程)上输出信息,但因为使用了 Task ,所以不用做任何处理 
                         while (!token.IsCancellationRequested) 
                        { 
                                Response.Write( "Task1 - " +  "ThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString()); 
                                Response.Write( "<br />"); 
                                Thread.Sleep(1000); 
                        } 

                } 
void Task2() 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 
        { 
void Page_Load() 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()); 
                }    
        } 


/* 
运行结果: 

10 
20 
30 
40 
50 
60 
70 
80 
90 
49.5 
49.5    
*/
 
 
注:关于并行运算的实例可以参考
http://code.msdn.microsoft.com/ParExtSamples


OK 
[源码下载]





     本文转自webabcd 51CTO博客,原文链接:http://blog.51cto.com/webabcd/341286,如需转载请自行联系原作者

相关文章
|
2月前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
2月前
|
编译器 C# 开发者
C# 11.0中的新特性:覆盖默认接口方法
C# 11.0进一步增强了接口的灵活性,引入了覆盖默认接口方法的能力。这一新特性允许类在实现接口时,不仅可以提供接口中未实现的方法的具体实现,还可以覆盖接口中定义的默认方法实现。本文将详细介绍C# 11.0中接口默认方法覆盖的工作原理、使用场景及其对现有代码的影响,帮助开发者更好地理解和应用这一新功能。
|
2月前
|
编译器 C# 开发者
C# 9.0中的顶级语句:简化程序入口的新特性
【1月更文挑战第13天】本文介绍了C# 9.0中引入的顶级语句(Top-level statements)特性,该特性允许开发者在不使用传统的类和方法结构的情况下编写简洁的程序入口代码。文章详细阐述了顶级语句的语法、使用场景以及与传统程序结构的区别,并通过示例代码展示了其在实际应用中的便捷性。
|
2月前
|
开发框架 .NET Java
ASP.NET Core高级编程--C#基本特性(一)
本文章简略介绍C#的部分特性
|
8月前
|
C#
c#之Attribute特性的原理
c#之Attribute特性的原理
30 0
|
12月前
|
数据可视化 程序员 C#
C# 面向对象三大特性
C# 面向对象三大特性
81 0
|
Rust 数据可视化 安全
【番外篇】Rust环境搭建+基础开发入门+Rust与.NET6、C++的基础运算性能比较
突然想打算把Rust作为将来自己主要的副编程语言。当然,主语言还是C#,毕竟.NET平台这么强大,写起来就是爽。缘起:之前打算一些新的产品或者新的要开发的东西,由于没有历史包袱,就想重新选型一下,在.NET平台(C#语言)、Golang、Rust里面进行选择一个。
268 0
【番外篇】Rust环境搭建+基础开发入门+Rust与.NET6、C++的基础运算性能比较
|
并行计算 Java C#
C#编程学习14:多线程并行程序设计及示例代码(下)
C#编程学习14:多线程并行程序设计及示例代码
C#编程学习14:多线程并行程序设计及示例代码(下)
|
SQL 开发框架 .NET
C#编程学习14:多线程并行程序设计及示例代码(上)
C#编程学习14:多线程并行程序设计及示例代码
C#编程学习14:多线程并行程序设计及示例代码(上)
|
C# 索引
【全栈计划 —— 编程语言之C#】总结深入面向对象三大特性之二 —— 继承性
【全栈计划 —— 编程语言之C#】总结深入面向对象三大特性之二 —— 继承性
89 0
【全栈计划 —— 编程语言之C#】总结深入面向对象三大特性之二 —— 继承性