C# 4.0 新特性之并行运算(Parallel)

介绍
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( 0 20 , (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


OK
[源码下载]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值