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+"\t");

           });    #######從零到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 的用法

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM