• 精进不休 .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
        {
            
    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


    OK
    [源码下载]
  • 相关阅读:
    python threading acquire release
    .net支付宝调试
    C#获取微信openid
    KindeEditor图片上传插件用法
    .net Repeater内部的按钮事件代码demo(Repeater内button的删除事件)
    .net 执行页面跳转弹窗提示,刷新代码
    .net验证控件
    上传图片
    数据库写入时间
    数据库读取
  • 原文地址:https://www.cnblogs.com/webabcd/p/1750449.html
Copyright © 2020-2023  润新知