線程同步-等待所有線程執行完畢

來源:互聯網
上載者:User

在多線程程式中經常會碰到線程同步:

情境1

主線程啟動多個子線程後,主線程需要等待所有的子線程執行完畢後,主線程才能進一步向下執行。

C# 提供了 ManualResetEvent 類為我們的線程同步提供了方便.

ManualResetEvent.WaitAll(new WaitHandle[] { });

 

WaitAll靜態方法提供了阻塞當前線程的執行,直到WaitHandle[]中的每個線程發送了阻塞解除的訊號,當前線程才會繼續執行。

 

可以通過將布爾值傳遞給建構函式來控制 ManualResetEvent 的初始狀態,如果初始狀態處於終止狀態,為 true;否則為 false。

 

ManualResetEvent.Set() 方法發送阻塞終止的訊號,當其它線程收到線程阻塞解除的訊號,就會繼續執行。

 

 

情境:主線程需要對子線程1產生的資料與子線程2產生的資料求和,主線程啟動線程1等待產生資料1,啟動線程2等待產生資料2,只有當

資料1與資料2產生後,主線程才能對資料求和。

 

代碼如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Diagnostics;namespace ThreadStudy.Hbb0b0{    /// <summary>    /// 本案例說明主線程如何等待輔助線程都執行完畢之後繼續執行。    /// 主線程啟動輔助線程1產生加數1,啟動輔助線程2產生加數2    /// 主線程等待輔助線程1與輔助線程2的產生的加數之後,對加數    /// 進行累加,並輸出結果。    /// </summary>    class Program    {        delegate int operateNumber(int a, int b);        delegate int generateNumber(int a);        static int result1;        static int result2;        static void Main(string[] args)        {            //輔助線程1阻塞標誌            ManualResetEvent m1 = new ManualResetEvent(false);                       //輔助線程2的阻塞標誌            ManualResetEvent m2 = new ManualResetEvent(false);             generateNumber g1 = ThreadTool.GenerateNumber;            generateNumber g2 = ThreadTool.GenerateNumber;            AsyncCallback g1_callback = delegate(IAsyncResult ar)            {                result1 = g1.EndInvoke(ar);                Console.WriteLine("thread id:{0} current number:{1} block stop", Thread.CurrentThread.ManagedThreadId, result1);                //輔助線程阻塞完畢                m1.Set();            };            AsyncCallback g2_callback = delegate(IAsyncResult ar)            {                result2 = g2.EndInvoke(ar);                Console.WriteLine("thread id:{0} current number:{1} block stop", Thread.CurrentThread.ManagedThreadId, result2);                //輔助線程阻塞完畢                m2.Set();            };            Console.WriteLine("generate numbers:");             //輔助線程1啟動            g1.BeginInvoke(10, g1_callback, null);                       //輔助線程2啟動            g2.BeginInvoke(100, g2_callback, null);             //主線線程等待所有輔助線程迴歸            ManualResetEvent.WaitAll(new WaitHandle[] { m1, m2 });             int sum= ThreadTool.sum(result1, result2);            Console.WriteLine("{0}+{1}={2}", result1, result2, sum);             Console.Read();         }    }    public class ThreadTool    {        /// <summary>        /// 產生數字        /// </summary>        /// <param name="maxNum"></param>        /// <returns></returns>        static public int GenerateNumber(int maxNum)        {            Console.WriteLine("thread Id:{0} generate number", Thread.CurrentThread.ManagedThreadId);            Thread.Sleep(5000);                    int result = new Random((int)DateTime.Now.Ticks).Next(maxNum);            return result;        }        /// <summary>        /// 累加結果        /// </summary>        /// <param name="a"></param>        /// <param name="b"></param>        /// <returns></returns>        static public int sum(int a, int b)        {            Console.WriteLine("thread Id:{0} gernerate number", Thread.CurrentThread.ManagedThreadId);            Thread.Sleep(6000);            return a + b;        }    }}

 

 

 

情境2 :

主線程啟動子線程1,子線程2, 只要子線程1或子線程2 任一線程執行完畢,主線程就可以繼續執行。

 

代碼如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace ThreadWaitOne{     class ThreadStartParameterInfo    {        /// <summary>        /// 線程訊號        /// </summary>        public ManualResetEvent m_mr;               /// <summary>        /// 線程等待時間        /// </summary>        public int m_waitTicks;        public ThreadStartParameterInfo(ManualResetEvent mr,int waitTicks)        {            m_mr = mr;            m_waitTicks = waitTicks;                  }    }     public class ThreadTool    {        private object m_SyncObject = new object();        private int currentThreadId = -1;        public void Main()        {            for (int i = 0; i < 5; i++)            {                ManualResetEvent mr1 = new ManualResetEvent(false);                ManualResetEvent mr2 = new ManualResetEvent(false);                ManualResetEvent mr3 = new ManualResetEvent(false);                ParameterizedThreadStart pts1 = new ParameterizedThreadStart(this.GenerateNumber);                ParameterizedThreadStart pts2 = new ParameterizedThreadStart(this.GenerateNumber);                ParameterizedThreadStart pts3 = new ParameterizedThreadStart(this.GenerateNumber);                Thread ts1 = new Thread(pts1);                Thread ts2 = new Thread(pts1);                Thread ts3 = new Thread(pts1);                ts1.Start (new ThreadStartParameterInfo(mr1, 3010));                ts2.Start(new ThreadStartParameterInfo(mr2, 3020));                ts3.Start(new ThreadStartParameterInfo(mr3, 3030));                //主線程等待任一線程,任一線程發送阻塞完成訊號後,主線程就可以繼續執行                ManualResetEvent.WaitAny(new WaitHandle[] { mr1, mr2, mr3 });                 Console.WriteLine("Main Thread: The fast thread:{0}", currentThreadId);            }                   }         public void GenerateNumber(object  resetEvent)        {            ThreadStartParameterInfo threadInfo = resetEvent as ThreadStartParameterInfo;            //ManualResetEvent mr = resetEvent as ManualResetEvent;            Console.WriteLine("thread Id:{0} wait:{1} generate number start:.....", Thread.CurrentThread.ManagedThreadId,threadInfo.m_waitTicks);                       Thread.Sleep(threadInfo.m_waitTicks);            int radomNumber = new Random((int)DateTime.Now.Ticks).Next(1000);            lock(m_SyncObject)            {                currentThreadId = Thread.CurrentThread.ManagedThreadId;            }            Console.WriteLine("thread Id:{0} generate number:{1}", Thread.CurrentThread.ManagedThreadId, radomNumber);            threadInfo.m_mr.Set();        }    }}

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.