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

相关文章
|
13天前
|
编译器 C# Android开发
震惊!Uno Platform 与 C# 最新特性的完美融合,你不可不知的跨平台开发秘籍!
Uno Platform 是一个强大的跨平台应用开发框架,支持 Windows、macOS、iOS、Android 和 WebAssembly,采用 C# 和 XAML 进行编程。C# 作为其核心语言,持续推出新特性,如可空引用类型、异步流、记录类型和顶级语句等,极大地提升了开发效率。要在 Uno Platform 中使用最新 C# 特性,需确保开发环境支持相应版本,并正确配置编译器选项。通过示例展示了如何在 Uno Platform 中应用可空引用类型、异步流、记录类型及顶级语句等功能,帮助开发者更好地构建高效、优质的跨平台应用。
134 59
|
14天前
|
SQL 开发框架 安全
并发集合与任务并行库:C#中的高效编程实践
在现代软件开发中,多核处理器普及使多线程编程成为提升性能的关键。然而,传统同步模型在高并发下易引发死锁等问题。为此,.NET Framework引入了任务并行库(TPL)和并发集合,简化并发编程并增强代码可维护性。并发集合允许多线程安全访问,如`ConcurrentQueue&lt;T&gt;`和`ConcurrentDictionary&lt;TKey, TValue&gt;`,有效避免数据不一致。TPL则通过`Task`类实现异步操作,提高开发效率。正确使用这些工具可显著提升程序性能,但也需注意任务取消和异常处理等常见问题。
26 1
|
1月前
|
SQL 存储 关系型数据库
C#一分钟浅谈:使用 ADO.NET 进行数据库访问
【9月更文挑战第3天】在.NET开发中,与数据库交互至关重要。ADO.NET是Microsoft提供的用于访问关系型数据库的类库,包含连接数据库、执行SQL命令等功能。本文从基础入手,介绍如何使用ADO.NET进行数据库访问,并提供示例代码,同时讨论常见问题及其解决方案,如连接字符串错误、SQL注入风险和资源泄露等,帮助开发者更好地利用ADO.NET提升应用的安全性和稳定性。
63 6
|
26天前
|
算法 Java 中间件
C#/.NET/.NET Core优质学习资料,干货收藏!
C#/.NET/.NET Core优质学习资料,干货收藏!
|
26天前
|
人工智能 开发框架 算法
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
|
26天前
|
缓存 开发框架 算法
C#/.NET这些实用的编程技巧你都会了吗?
C#/.NET这些实用的编程技巧你都会了吗?
|
26天前
|
传感器 应用服务中间件 Linux
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
|
26天前
|
人工智能 算法 C#
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
|
26天前
|
JSON 测试技术 C#
C#/.NET/.NET Core优秀项目框架推荐榜单
C#/.NET/.NET Core优秀项目框架推荐榜单
|
26天前
|
开发框架 .NET Java
C#/.NET/.NET Core自学入门指南
C#/.NET/.NET Core自学入门指南