CountdownEvent 任务并行库使用小计


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CountdownEventApplication
{
    /**
     *
     *
     * System.Threading.CountdownEvent  是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定。
     * CountdownEvent  专门用于以下情况:您必须使用 ManualResetEvent 或 ManualResetEventSlim,并且必须在用信号通知事件之前手动递减一个变量。
     * 例如,在分叉/联接方案中,您可以只创建一个信号计数为 5 的 CountdownEvent,然后在线程池上启动五个工作项,并且让每个工作项在完成时调用 Signal。
     * 每次调用 Signal 时,信号计数都会递减 1。 在主线程上,对 Wait 的调用将会阻塞,直至信号计数为零。
     * CountdownEvent  具有这些附加功能:
     * •可通过使用取消标记来取消等待操作。
     * •创建实例之后可以递增它的信号计数。
     * •通过调用 Reset 方法,可在 Wait 返回之后重用实例。
     * •实例公开 WaitHandle 以便与其他 .NET Framework 同步 API(例如 WaitAll)进行集成。
     * 
     **/
    class Program
    {
        static CountdownEvent cde = null;
        static int overLimitTime = 5000;//第一期工作完成时间
        /// <summary>
        /// 模拟建房子
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            try
            {
                #region 普通示例
                //建房子第一期工人
                string[] _bhPerson1 = new string[5] { "Yan", "Zhi", "wei", "Do", "Work" };
                //建房子第二期工人
                string[] _bhPerson2 = new string[3] { "Yan2", "Zhi2", "wei2" };
                //建房子第三期工人
                string[] _bhPerson3 = new string[3] { "Yan3", "Zhi3", "wei3" };
                using (cde = new CountdownEvent(Environment.ProcessorCount))//开始监管,相当于监工
                {
                    cde.Reset(_bhPerson1.Length);//设置第一期建造需要5个人
                    foreach (string person in _bhPerson1)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            BuilderHourseStep1(person);
                        });
                    }
                    cde.Wait();//等待第一期建造完成
                    Console.WriteLine("-----------------------");
                    cde.Reset(_bhPerson2.Length);//设置第二期建需要三个人
                    foreach (string person in _bhPerson2)
                    {
                        Task.Factory.StartNew(() =>
                          {
                              BuilderHourseStep2(person);
                          });
                    }
                    cde.Wait();//等待第二期建造完成
                    Console.WriteLine("-----------------------");
                    cde.Reset(_bhPerson3.Length);//设置第三期建需要三个人
                    foreach (string person in _bhPerson3)
                    {
                        Task.Factory.StartNew(() =>
                            {
                                BuilderHourseStep3(person);
                            });
                    }
                    cde.Wait();//等待第三期建造完成
                    Console.WriteLine("-----------------------");
                }
                #endregion
                #region 超时演示,延续上面例子,建造房子存在延期的情况,譬如某个工作工作懒散,那么需要给整个一期建造设置一个总的时限。
                using (cde = new CountdownEvent(Environment.ProcessorCount))//开始监管,相当于监工
                {
                    cde.Reset(_bhPerson1.Length);//设置第一期建造需要5个人
                    Random _workTime = new Random();
                    foreach (string person in _bhPerson1)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            int _doWorkTime = _workTime.Next(3000, 6000);//工人工作时间
                            BuilderHourseStep1(person, _doWorkTime);
                        });
                    }
                    bool _bdStep1Result = cde.Wait(overLimitTime);
                    Console.WriteLine(string.Format("第一期建造状态:{0}.", _bdStep1Result == true ? "完成" : "延时"));//等待第一期建造完成 限制5秒内完成
                    Console.WriteLine("-----------------------");
                    if (!_bdStep1Result) return;
                    cde.Reset(_bhPerson2.Length);//设置第二期建需要三个人
                    foreach (string person in _bhPerson2)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            BuilderHourseStep2(person);
                        });
                    }
                    cde.Wait();//等待第二期建造完成
                    Console.WriteLine("-----------------------");
                    cde.Reset(_bhPerson3.Length);//设置第三期建需要三个人
                    foreach (string person in _bhPerson3)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            BuilderHourseStep3(person);
                        });
                    }
                    cde.Wait();//等待第三期建造完成
                    Console.WriteLine("-----------------------");
                }
                #endregion
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Excepton Message: {0}", ex.Message.Trim()));
            }
            finally
            {
                Console.ReadKey();
            }
        }
        /// <summary>
        /// 建房子第一道所需要的工序
        /// </summary>
        /// <param name="person"></param>
        static void BuilderHourseStep1(string person)
        {
            try
            {
                Console.WriteLine(string.Format("『{0}』BuilderHourseStep1....", person));
            }
            finally
            {
                cde.Signal();//建造完成一点后,通知监工
            }
        }
        /// <summary>
        /// 建房子第一道所需要的工序
        /// </summary>
        /// <param name="person"></param>
        static void BuilderHourseStep1(string person, int doWorkTime)
        {
            bool _isDoWork = doWorkTime < overLimitTime;
            try
            {
                if (_isDoWork)
                    Console.WriteLine(string.Format("『{0}』做事情花费了,{1}s........", person, doWorkTime));
                else
                    Console.WriteLine(string.Format("『{0}』做事情太墨迹,花费了{1}s....", person, doWorkTime));
                Thread.Sleep(doWorkTime);
            }
            finally
            {
                if (_isDoWork)
                    cde.Signal();//建造完成后,通知监工
            }
        }
        /// <summary>
        /// 建房子第二道所需要的工序
        /// </summary>
        /// <param name="person"></param>
        static void BuilderHourseStep2(string person)
        {
            try
            {
                Console.WriteLine(string.Format("『{0}』BuilderHourseStep2.....", person));
            }
            finally
            {
                cde.Signal();
            }
        }
        /// <summary>
        /// 建房子第三道所需要的工序
        /// </summary>
        /// <param name="person"></param>
        static void BuilderHourseStep3(string person)
        {
            try
            {
                Console.WriteLine(string.Format("『{0}』BuilderHourseStep3.......", person));
            }
            finally
            {
                cde.Signal();
            }
        }
    }
}

知识共享许可协议
《CountdownEvent 任务并行库使用小计》常伟华 创作。
采用 知识共享 署名-相同方式共享 3.0 中国大陆 许可协议进行许可。
相邻依据:发表时间
  • 多说评论
  • 签名
  • 新浪微博
  • 默认评论
  • Tab Header 5

0 条评论 / 点击此处发表评论

Tab Content 5

开发技术


开发平台和工具

sitemap     161.36ms