using System;

namespace ConsoleApplication1
{
    #region P1
    ///// <summary>
    ///// 从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,
    ///// 对他的老板总是百依百顺。但是他的老板是个吝啬的人,从不信任别人,
    ///// 坚决要求随时知道彼得的工作进度,以防止他偷懒。但是彼得又不想让
    ///// 老板呆在他的办公室里站在背后盯着他,于是就对老板做出承诺:无论
    ///// 何时,只要我的工作取得了一点进展我都会及时让你知道。彼得通过周
    ///// 期性地使用“带类型的引用”(原文为:“typed reference” 也就是
    ///// delegate??)“回调”他的老板来实现他的承诺,如下
    ///// </summary>
    //class Worker
    //{
    //    private Boss _boss;
    //    public void Advise(Boss boss) { _boss = boss; }
    //    public void DoWork()
    //    {
    //        Console.WriteLine("工作: 工作开始");
    //        if (_boss != null) _boss.WorkStarted();

    //        Console.WriteLine("工作: 工作进行中");
    //        if (_boss != null) _boss.WorkProgressing();

    //        Console.WriteLine("工作: 工作完成");
    //        if (_boss != null)
    //        {
    //            int grade = _boss.WorkCompleted();
    //            Console.WriteLine("工人的工作得分=" + grade);
    //        }
    //    }

    //}

    //class Boss
    //{
    //    public void WorkStarted() { /* 老板不关心。 */ }
    //    public void WorkProgressing() { /*老板不关心。 */ }
    //    public int WorkCompleted()
    //    {
    //        Console.WriteLine("时间差不多!");
    //        return 2; /* 总分为10 */
    //    }
    //}

    //class Universe
    //{
    //    static void Main()
    //    {
    //        Worker peter = new Worker();
    //        Boss boss = new Boss();
    //        peter.Advise(boss);
    //        peter.DoWork();

    //        Console.WriteLine("Main: 工人工作完成");
    //        Console.ReadLine();
    //    }
    //}

    #endregion

    #region P2

    ///// <summary>
    ///// 现在,彼得成了一个特殊的人,
    ///// 他不但能容忍吝啬的老板,而
    ///// 且和他周围的宇宙也有了密切的联系,
    ///// 以至于他认为宇宙对他的工作进度也感兴趣。
    ///// 不幸的是,他必须也给宇宙添加一个特殊的
    ///// 回调函数Advise来实现同时向他老板和宇宙
    ///// 报告工作进度。彼得想要把潜在的通知的列
    ///// 表和这些通知的实现方法分离开来,于是他
    ///// 决定把方法分离为一个接口
    ///// </summary>
    //public interface IWorkerEvents
    //{
    //    void WorkStarted();
    //    void WorkProgressing();
    //    int WorkCompleted();
    //}

    //public class Worker
    //{
    //    public void Advise(IWorkerEvents events)
    //    {
    //        this._events = events;
    //    }
    //    public void DoWork()
    //    {
    //        Console.WriteLine("工作:工作开始");
    //        if (_events != null)
    //        {
    //            _events.WorkStarted();
    //        }
    //        Console.WriteLine("工作:工作进行中");
    //        if (_events != null)
    //        {
    //            _events.WorkProgressing();
    //        }
    //        Console.WriteLine("工作:工作完成");
    //        if (_events != null)
    //        {
    //            int grade = _events.WorkCompleted();
    //            Console.WriteLine("工人的工作得分={0}", grade);
    //        }
    //    }
    //    private IWorkerEvents _events;

    //}
    //public class Boss : IWorkerEvents
    //{


    //    #region IWorkerEvents Members

    //    public void WorkStarted()
    //    {
    //        //throw new NotImplementedException();
    //    }

    //    public void WorkProgressing()
    //    {
    //        //throw new NotImplementedException();
    //    }

    //    public int WorkCompleted()
    //    {
    //        return 5;
    //    }


    //    #endregion
    //}
    //public class Universe : IWorkerEvents
    //{

    //    #region IWorkerEvents Members

    //    public void WorkStarted()
    //    {
    //       // throw new NotImplementedException();
    //    }

    //    public void WorkProgressing()
    //    {
    //        //throw new NotImplementedException();
    //    }

    //    public int WorkCompleted()
    //    {
    //        //throw new NotImplementedException();
    //        return 8;
    //    }

    //    #endregion
    //}

    //public class Programme
    //{
    //    static void Main()
    //    {
    //        Worker worker = new Worker();
    //        worker.Advise(new Boss());
    //        worker.DoWork();
    //        worker.Advise(new Universe());
    //        worker.DoWork();//由此可见无法同时通知宇宙和老板
    //        Console.ReadLine();
    //    }
    //}
    #endregion

    #region P3

    //  delegate void WorkStarted();
    //  delegate void WorkProgress();
    //  delegate int WorkCompleted();

    //  /// <summary>
    //  /// 他的老板还是抱怨得很厉害。“彼得!”他老板吼道,“你为什么在工作一开始和工作进行中都来烦我?!我不关心这些事件。你不但强迫我实现了这些方法,而且还在浪费我宝贵的工作时间来处理你的事件,特别是当我外出的时候更是如此!你能不能不再来烦我?”

    /////于是,彼得意识到接口虽然在很多情况都很有用,但是当用作事件时,“粒度”不够好。他希望能够仅在别人想要时才通知他们,于是他决定把接口的方法分离为单独的委托,每个委托都像一个小的接口方法:
    //  /// </summary>
    //  class Worker
    //  {
    //      public void DoWork()
    //      {
    //          Console.WriteLine("工作:工作开始");
    //          if (started != null)
    //          {
    //              started();
    //          }
    //          Console.WriteLine("工作:工作进行中");
    //          if (progressing != null)
    //          {
    //              progressing();
    //          }
    //          Console.WriteLine("工作:工作完成");
    //          if (completed != null)
    //          {
    //              int grade = completed();
    //              Console.WriteLine("工人的工作得分={0}", grade);
    //          }
    //      }
    //      public WorkCompleted completed;
    //      public WorkProgress progressing;
    //      public WorkStarted started;

    //  }

    //  class Boss
    //  {
    //      public int WorkComplete()
    //      {
    //          Console.WriteLine("Better...");
    //          return 4;
    //      }
    //      public void WorkProgressing()
    //      {
    //          Console.WriteLine("okok,i am boss");
    //      }
    //  }

    //  class Universe
    //  {
    //      static void Main()
    //      {
    //          Worker worker = new Worker();
    //          Boss b = new Boss();
    //          Universe u = new Universe();
    //          worker.progressing = new WorkProgress(u.WorkProgressMethod);
    //          worker.progressing += new WorkProgress(b.WorkProgressing);
    //          worker.completed = new WorkCompleted(b.WorkComplete);
    //          worker.DoWork();
    //          Console.ReadLine();
    //      }
    //      public void WorkProgressMethod()
    //      {
    //          Console.WriteLine("okok,i am universe...");
    //      }
    //  }

    #endregion

    #region P4

    ///// <summary>
    ///// 这样,彼得不会再拿他老板不想要的事件来烦他老板了,
    ///// 但是他还没有把宇宙放到他的监听者列表中。因为宇宙是
    ///// 个包涵一切的实体,看来不适合使用实例方法的委托(想
    ///// 像一下,实例化一个“宇宙”要花费多少资源…..),于
    ///// 是彼得就需要能够对静态委托进行挂钩,委托对这一点支持得很好
    ///// </summary>
    //class Universe
    //{
    //    static void WorkerStartedWork()
    //    {
    //        Console.WriteLine("Universe notices worker starting work");
    //    }

    //    static int WorkerCompletedWork()
    //    {
    //        Console.WriteLine("Universe pleased with worker's work");
    //        return 7;
    //    }

    //    static void Main()
    //    {
    //        Worker peter = new Worker();
    //        Boss boss = new Boss();
    //        peter.completed = new WorkCompleted(boss.WorkCompleted);
    //        peter.started = new WorkStarted(Universe.WorkerStartedWork);
    //        peter.completed = new WorkCompleted(Universe.WorkerCompletedWork);
    //        peter.DoWork();

    //        Console.WriteLine("Main: 工人工作完成");
    //        Console.ReadLine();
    //    }
    //}

    #endregion

    #region P5 事件
// //  不幸的是,宇宙太忙了,
    //也不习惯时刻关注它里面的个体,它可以用自己的委托替换了彼得老板的委托。这是把彼得的Worker类的的委托字段做成public的一个无意识的副作用。同样,如果彼得的老板不耐烦了,也可以决定自己来激发彼得的委托(真是一个粗鲁的老板):

//// Peter's boss taking matters into his own hands
//if( peter.completed != null ) peter.completed();

//  彼得不想让这些事发生,他意识到需要给每个委托提供“注册”和“反注册”功能,这样监听者就可以自己添加和移除委托,但同时又不能清空整个列表也不能随意激发彼得的事件了。彼得并没有来自己实现这些功能,相反,他使用了event关键字让C#编译器为他构建这些方法:

//class Worker {
//...
//    public event WorkStarted started;
//    public event WorkProgressing progressing;
//    public event WorkCompleted completed;
//}

//  彼得知道event关键字在委托的外边包装了一个property,仅让C#客户通过+= 和 -=操作符来添加和移除,强迫他的老板和宇宙正确地使用事件。

//static void Main() {
//    Worker peter = new Worker();
//    Boss boss = new Boss();
//    peter.completed += new WorkCompleted(boss.WorkCompleted);
//    peter.started += new WorkStarted(Universe.WorkerStartedWork);
//    peter.completed += new WorkCompleted(Universe.WorkerCompletedWork);
//    peter.DoWork();

//    Console.WriteLine(“Main: 工人工作完成”);
//    Console.ReadLine();
//}

    #endregion

    #region P6 收获所有结果
    //delegate void WorkStarted();
    //delegate void WorkProgress();
    //delegate int WorkCompleted();

    ///// <summary>
    ///// 他的老板还是抱怨得很厉害。“彼得!”他老板吼道,
    ///// “你为什么在工作一开始和工作进行中都来烦我?!
    ///// 我不关心这些事件。你不但强迫我实现了这些方法,
    ///// 而且还在浪费我宝贵的工作时间来处理你的事件,特别
    ///// 是当我外出的时候更是如此!你能不能不再来烦我?”
    /////于是,彼得意识到接口虽然在很多情况都很有用,但是当
    /////用作事件时,“粒度”不够好。他希望能够仅在别人想要
    /////时才通知他们,于是他决定把接口的方法分离为单独的委
    /////托,每个委托都像一个小的接口方法:
    ///// </summary>
    //class Worker
    //{
    //    public void DoWork()
    //    {
    //        Console.WriteLine("工作:工作开始");
    //        if (started != null)
    //        {
    //            started();
    //        }
    //        Console.WriteLine("工作:工作进行中");
    //        if (progressing != null)
    //        {
    //            progressing();
    //        }
    //        Console.WriteLine("工作:工作完成");
    //        if (completed != null)
    //        {
    //            int grade = completed();
    //            Console.WriteLine("工人的工作得分={0}", grade);
    //        }
    //        Console.WriteLine("下面是所有监听者的情况:");
    //        if (completed != null)
    //        {
    //            foreach (WorkCompleted wc in completed.GetInvocationList())//收获所有结果
    //            {
    //                Console.WriteLine("{0}", wc());
    //            }
    //        }
    //    }
    //    public event WorkCompleted completed;
    //    public event WorkProgress progressing;
    //    public event WorkStarted started;

    //}

    //class Boss
    //{
    //    public int WorkComplete()
    //    {
    //        Console.WriteLine("Better...");
    //        return 4;
    //    }
    //    public void WorkProgressing()
    //    {
    //        Console.WriteLine("okok,i am boss");
    //    }
    //}

    //class Universe
    //{
    //    static void Main()
    //    {
    //        Worker worker = new Worker();
    //        Boss b = new Boss();
    //        Universe u = new Universe();
    //        worker.completed += new WorkCompleted(b.WorkComplete);
    //        worker.completed += new WorkCompleted(u.WorkCompletedMethod);
    //        worker.DoWork();
    //        Console.ReadLine();
    //    }
    //    public int WorkCompletedMethod()
    //    {
    //        Console.WriteLine("okok,i am universe...");
    //        return 8;
    //    }
    //}
    #endregion

    #region F7 异步通知&忘掉
    delegate void WorkStarted();
    delegate void WorkProgress();
    delegate int WorkCompleted();

    /// <summary>
    /// 同时,他的老板和宇宙还要忙于处理其他事情,
    /// 也就是说他们给彼得打分所花费的事件变得非常长:
    /// 很不幸,彼得每次通知一个监听者后必须等待它给
    /// 自己打分,现在这些通知花费了他太多的工作事件。
    /// 于是他决定忘掉分数,仅仅异步激发事件
    /// </summary>
    class Worker
    {
        public void DoWork()
        {
            Console.WriteLine("工作:工作开始");
            if (started != null)
            {
                started();
            }
            Console.WriteLine("工作:工作进行中");
            if (progressing != null)
            {
                progressing();
            }
            Console.WriteLine("工作:工作完成");
            //if (completed != null)
            //{
            //    int grade = completed();
            //    Console.WriteLine("工人的工作得分={0}", grade);
            //}
            //Console.WriteLine("下面是所有监听者的情况:");
            if (completed != null)
            {
                foreach (WorkCompleted wc in completed.GetInvocationList())//收获所有结果
                {
                    //wc.BeginInvoke(null, null);//如果不需要返回结果
                    //Console.WriteLine("{0}", wc());

                    //IAsyncResult res = wc.BeginInvoke(null, null);//需要返回结果
                    //while (!res.IsCompleted)//轮询,等待获取结果
                    //{
                    //    System.Threading.Thread.Sleep(1);
                    //    int grade = wc.EndInvoke(res);
                    //    Console.WriteLine("工人的工作得分={0}", grade);
                    //}

                    wc.BeginInvoke(new AsyncCallback(WorkGraded), wc);//异步通知:委托
                }
            }

            Console.WriteLine("Do other thing");
        }
        void WorkGraded(IAsyncResult res)
        {
            WorkCompleted wc = res.AsyncState as WorkCompleted;
            int grade = wc.EndInvoke(res);
            Console.WriteLine("得到工人的工作得分={0}", grade);
        }
        public event WorkCompleted completed;
        public event WorkProgress progressing;
        public event WorkStarted started;

    }

    class Boss
    {
        public int WorkComplete()
        {
            System.Threading.Thread.Sleep(3000);
            Console.WriteLine("okok,i am boss...");
            return 4;
        }
        
    }

    class Universe
    {
        static void Main()
        {
            Worker worker = new Worker();
            Boss b = new Boss();
            Universe u = new Universe();
            worker.completed += new WorkCompleted(b.WorkComplete);
            worker.completed += new WorkCompleted(u.WorkCompletedMethod);
            worker.DoWork();
            Console.ReadLine();
        }
        public int WorkCompletedMethod()
        {
            System.Threading.Thread.Sleep(4000);
            Console.WriteLine("okok,i am universe...");
            return 8;
        }
    }

    #endregion

}

 

宇宙中的幸福

  彼得、他的老板和宇宙最终都满足了。彼得的老板和宇宙可以收到他们感兴趣的事件通知,减少了实现的负担和非必需的往返“差旅费”。彼得可以通知他们,而不管他们要花多长时间来从目的方法中返回,同时又可以异步地得到他的结果。彼得知道,这并不*十分*简单,因为当他异步激发事件时,方法要在另外一个线程中执行,彼得的目的方法完成的通知也是一样的道理。但是,迈克和彼得是好朋友,他很熟悉线程的事情,可以在这个领域提供指导。

  他们永远幸福地生活下去……<完>

posted on 2010-03-20 23:22  kuning的程序博客  阅读(240)  评论(0编辑  收藏  举报