线程同步-等待所有线程执行完毕

在多线程程序中经常会碰到线程同步:

场景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();



        }



    }



}

 

 

 

 

你可能感兴趣的:(线程同步)