• C# Parallel并发执行相关问题


    1、Parallel并发执行

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Diagnostics;
    using System.Threading;
    using System.Configuration;
    using System.Collections.Concurrent;
    namespace ConsoleApplication57
    {
        class Program
        {
            static void Main(string[] args)
            {
                ParallelDemo BingFa = new ParallelDemo();
                BingFa.ParallelInvokemethod();
                Console.ReadKey();  
                BingFa.ParallelForMethod();
                Console.ReadKey();
                BingFa.ParallelForMethod2();
                BingFa.ParallelBreak();
            }
        }
        public class ParallelDemo {
            private Stopwatch stopWatch = new Stopwatch();
            public void Run1() {
                Thread.Sleep(2000);
                Console.WriteLine("Task 1 is cost 2 sec");
            }
            public void Run2() {
                Thread.Sleep(3000);
                Console.WriteLine("Task 2 is cost 3  sec");
            }
            public void ParallelInvokemethod() {
                stopWatch.Start();
                Parallel.Invoke(Run1, Run2);
                stopWatch.Stop();
                Console.WriteLine("Parallel run" + stopWatch.ElapsedMilliseconds + "ms");
                stopWatch.Restart();
                Run1();
                Run2();
                stopWatch.Stop();
                Console.WriteLine("Normall run"+stopWatch.ElapsedMilliseconds+"ms");
            }
            public void ParallelForMethod() {
                stopWatch.Start();
                for (int i = 0; i < 10000; i++) {
                    for (int j = 0; j < 60000; j++) {
                        int sum = 0;
                        sum += i;
                    }
                }
                stopWatch.Stop();
                Console.WriteLine("Normalfor run" + stopWatch.ElapsedMilliseconds + "ms");
                stopWatch.Reset();
                stopWatch.Start();
                Parallel.For(0, 10000, item =>
                {
                    for (int j = 0; j < 60000; j++)
                    {
                        int sum = 0;
                        sum += item;
                    }
                });
                stopWatch.Stop();
                Console.WriteLine("ParallelFor run" + stopWatch.ElapsedMilliseconds + "ms");
            }
            public void ParallelForMethod2() {
                var obj = new Object();
                long num = 0;
                ConcurrentBag<long> bag = new ConcurrentBag<long>();
                stopWatch.Start();
                for (int i = 0; i < 10000; i++) {
                    for (int j = 0; j < 60000; j++)
                    {
                        num++;
                    }
                }
                    stopWatch.Stop();
                Console.WriteLine("NormalFor run"+stopWatch.ElapsedMilliseconds+"ms");
                stopWatch.Reset();
                stopWatch.Start();
                Parallel.For(0,10000,item=>{
                for(int j=0;j<60000;j++){
                lock(obj){
                num++;
                }}});
                stopWatch.Stop();
                Console.WriteLine("ParallelFor run"+stopWatch.ElapsedMilliseconds+"ms");
                Console.ReadKey();


            }
            public void ParallelBreak()
            {
                ConcurrentBag<int> bag = new ConcurrentBag<int>();
                stopWatch.Start();
                Parallel.For(0, 1000, (i, state) =>
                {
                    if (bag.Count == 300)
                    {
                        state.Stop();
                        return;
                    }
                    bag.Add(i);
                });
                stopWatch.Stop();
                Console.WriteLine("Bag count is {}{}", bag.Count, stopWatch.ElapsedMilliseconds+"ms");

            }
            //</long></long>
        }
        
        //public void  ParallelForMethod{
    //}
    }


    2 、使用Parallel来做循环

           Parallel.For(0,100,i=>{

                    Console.writeLine(i+" ");

               });    #######从零到99,运行或输出的顺序不对,但是使用for循环的,并行执行的时候会初夏输出顺序不同的问题。

         Parallel.Foreach和foreach很类似,

            List<int> list=new List<int>();

                       list.Add(0);

                 Parallel.ForEach(list,item=>{

                        DoWork(item);

                   });

    3、异常处理  

          由于执行的任务是并发的执行的,产生的异常回是多个,简单的Exception不能获取异常,使用AggregateException课可以捕获到一组异常

         

    Task pt = new Task(() =>
    {
        Task.Factory
            .StartNew(() =>
            {
                throw new Exception("ex 1");
            }, TaskCreationOptions.AttachedToParent);
    
        Task.Factory
            .StartNew(() =>
            {
                Task.Factory
                    .StartNew(() =>
                    {
                        throw new Exception("ex 2-1");
                    }, TaskCreationOptions.AttachedToParent);
    
                throw new Exception("ex 2");
            }, TaskCreationOptions.AttachedToParent);
    
        throw new Exception("ex 3");
    });

    pt.Start()开始任务,异常不会抛出,但必须被处理,以下是若干种方法。

    //方法1:
    pt.ContinueWith(t =>
    {
        t.Exception.Handle(ex =>
        {
            Console.WriteLine(ex.Message);
            return true;
        });
    }, TaskContinuationOptions.OnlyOnFaulted);
    //方法2:
    pt.ContinueWith(t =>
    {
        t.Exception.Handle(ex =>
        {
            Console.WriteLine(ex.GetBaseException().Message);
            return true;
        });
    }, TaskContinuationOptions.OnlyOnFaulted);
    //方法3:
    pt.ContinueWith(t =>
    {
        foreach (var ex in t.Exception.Flatten().InnerExceptions)
        {
            Console.WriteLine(ex.Message);
        }
    }, TaskContinuationOptions.OnlyOnFaulted);
    //方法4:
    pt.ContinueWith(t =>
    {
        foreach (var ex in t.Exception.InnerExceptions)
        {
            Console.WriteLine(ex.Message);
        }
    }, TaskContinuationOptions.OnlyOnFaulted);

    5、线程并行安全,如下执行的时候输出错误,这是因为List是非线程安全集合,所有的线程都可以修改他的值,造成线程的安全问题。

    ---------- namespace ConsoleApplication58
    {
        class Program
        {
            static void Main(string[] args)
            {
                PEnumberable Test = new PEnumberable();
                Test.ListWithpallel();
                Console.ReadKey();
            }
        }
        public class PEnumberable {
            public  void ListWithpallel() {
                List<int> list = new List<int>();
                Parallel.For(0, 1000, item =>
                {
                    list.Add(item);
                });
                Console.WriteLine("list count is{0}",list.Count());
            }  }}

    ################

              使用system.Collection.Concurrent, 实例ConcurrentBag泛型集合

     public void ConcurrentBagwithPallel() {
                ConcurrentBag<int> list = new ConcurrentBag<int>();
                Parallel.For(0, 10000, item =>
                {
                    list.Add(item);
                });
                Console.WriteLine("ConcurrentBag's count is{0}", list.Count());

            }

      

    现在我们看看 ConcurrentBag中的数据是怎么排列的

     public void ConcurrentBagwithPallel() {
                ConcurrentBag<int> list = new ConcurrentBag<int>();
                Parallel.For(0, 10000, item =>
                {
                    list.Add(item);
                });
                Console.WriteLine("ConcurrentBag's count is{0}", list.Count());
                int n = 0;
                foreach (int i in list) {
                    if (n > 10)
                        break;
                    n++; Console.WriteLine("Item{0}={1}", n, i);
                   
                }
                Console.WriteLine("ConcurrentBag's max item is{0]", list.Max());

            }

    从上面的执行可窥看出ConcurentBag中的数据排序是乱序的,但是属性Max ,Frist ,Last等都可以使用,关于线程安全的问题还用 Dictionary 的ConcurrentDictionary还用 ConcurrentStack,ConcurrentQueue等

    6、Parallel  Linq 的用法

         

  • 相关阅读:
    centos 安装docker
    vsphere client 创建虚拟机 如何关联到本地iso文件
    在centos7中使用supermin制作centos6.5docker镜像
    centos安装后,连接不上网络,yum命令执行can not find a valid baseurl for repo: base/7/x86-64
    佛祖保佑,永无BUG
    框架原理
    android 中解析XML的方法(转)
    android 项目随记一
    android事件系列-onTouch事件与手势操作
    深入理解 AngularJS 的 Scope(转)
  • 原文地址:https://www.cnblogs.com/xinxianquan/p/9767597.html
Copyright © 2020-2023  润新知