精进不休 .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,如需转载请自行联系原作者

相关文章
|
15天前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
1月前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
1月前
|
SQL 数据库 C#
C# .NET面试系列十一:数据库SQL查询(附建表语句)
#### 第1题 用一条 SQL 语句 查询出每门课都大于80 分的学生姓名 建表语句: ```sql create table tableA ( name varchar(10), kecheng varchar(10), fenshu int(11) ) DEFAULT CHARSET = 'utf8'; ``` 插入数据 ```sql insert into tableA values ('张三', '语文', 81); insert into tableA values ('张三', '数学', 75); insert into tableA values ('李四',
65 2
C# .NET面试系列十一:数据库SQL查询(附建表语句)
|
1月前
|
开发框架 算法 搜索推荐
C# .NET面试系列九:常见的算法
#### 1. 求质数 ```c# // 判断一个数是否为质数的方法 public static bool IsPrime(int number) { if (number < 2) { return false; } for (int i = 2; i <= Math.Sqrt(number); i++) { if (number % i == 0) { return false; } } return true; } class Progr
58 1
|
8天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
1月前
|
开发框架 人工智能 .NET
C#/.NET/.NET Core拾遗补漏合集(持续更新)
C#/.NET/.NET Core拾遗补漏合集(持续更新)
|
1月前
|
SQL 存储 关系型数据库
C# .NET面试系列十:数据库概念知识
#### 1. 为什么要一定要设置主键? 设置主键是数据库设计中的一个重要概念,有几个主要原因: 1、唯一性 ```c# 主键必须保证表中的每一行都有唯一的标识。这样可以避免数据冗余和不一致性。如果没有主键或者主键不唯一,就可能出现数据混乱或错误。 ``` 2、查询性能 ```c# 数据库系统通常会使用主键来加速数据检索。主键通常会被索引,这样可以更快速地找到特定行的数据,提高查询效率。 ``` 3、关联性 ```c# 主键常常用于建立表与表之间的关系。在关系数据库中,一个表的主键通常与其他表中的外键建立关联,这种关系对于数据的一致性和完整性非常重要。 ``` 4、数据完
131 1
C# .NET面试系列十:数据库概念知识
|
1月前
|
XML 开发框架 .NET
C# .NET面试系列八:ADO.NET、XML、HTTP、AJAX、WebService
## 第二部分:ADO.NET、XML、HTTP、AJAX、WebService #### 1. .NET 和 C# 有什么区别? .NET(通用语言运行时): ```c# 定义:.NET 是一个软件开发框架,提供了一个通用的运行时环境,用于在不同的编程语言中执行代码。 作用:它为多语言支持提供了一个统一的平台,允许不同的语言共享类库和其他资源。.NET 包括 Common Language Runtime (CLR)、基础类库(BCL)和其他工具。 ``` C#(C Sharp): ```c# 定义: C# 是一种由微软设计的面向对象的编程语言,专门为.NET 平台开发而创建。 作
174 2
|
1月前
|
开发框架 中间件 .NET
C# .NET面试系列七:ASP.NET Core
## 第一部分:ASP.NET Core #### 1. 如何在 controller 中注入 service? 在.NET中,在ASP.NET Core应用程序中的Controller中注入服务通常使用<u>依赖注入(Dependency Injection)</u>来实现。以下是一些步骤,说明如何在Controller中注入服务: 1、创建服务 首先,确保你已经在应用程序中注册了服务。这通常在Startup.cs文件的ConfigureServices方法中完成。例如: ```c# services.AddScoped<IMyService, MyService>(); //
61 0
|
1月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
95 5