16订阅者方法超时的处理

订阅者方法超时会让客户端程序出现某种程度的中断。
模拟考试,比较现实的状况是谁先答完,谁先交试卷,不可能按学生序号来决定交试卷顺序。

  先模拟一个订阅者方法超时

□ 老师的职责是组织考试,并让每个注册学生(订阅者)答题。

   1:      public class Teacher
   2:      {
   3:          public event EventHandler TestEvent;
   4:   
   5:          public void Test()
   6:          {
   7:              Console.WriteLine("老师:同学们,现在开始考试");
   8:   
   9:              //触发事件的所有注册方法
  10:              //实际上也有返回值的,只不过没有获取
  11:              //第二个参数是被监视对象,相当于object sender
  12:              EventHelper.FireEvent(TestEvent, this, EventArgs.Empty);
  13:          }
  14:      }


□ EventHelper是关于触发注册方法的静态类。主要是遍历委托链表,让链表上的每个方法得以执行

3

□ 学生的职责是考试,答题速度有快有慢

   1:      public class Student1
   2:      {
   3:          public void DoTest(Object sender, EventArgs e)
   4:          {
   5:              Thread.Sleep(TimeSpan.FromSeconds(3));
   6:              Console.WriteLine("Student1用了3秒钟答题交试卷了");
   7:          }
   8:      }
   9:   
  10:      public class Student2
  11:      {
  12:          public void DoTest(Object sender, EventArgs e)
  13:          {
  14:              Thread.Sleep(TimeSpan.FromSeconds(2));
  15:              Console.WriteLine("Student2用了2秒钟答题交试卷了");
  16:          }
  17:      }
  18:   
  19:      public class Student3
  20:      {
  21:          public void DoTest(Object sender, EventArgs e)
  22:          {
  23:              Thread.Sleep(TimeSpan.FromSeconds(1));
  24:              Console.WriteLine("Student3用了1秒钟答题交试卷了");
  25:          }
  26:      }

□ 主程序注册方法,老师触发宣布考试开始

   1:      class Program
   2:      {
   3:          static void Main(string[] args)
   4:          {
   5:              Teacher teacher = new Teacher();
   6:              Student1 student1 = new Student1();
   7:              Student2 student2 = new Student2();
   8:              Student3 student3 = new Student3();
   9:   
  10:              teacher.TestEvent += new EventHandler(student1.DoTest);
  11:              teacher.TestEvent += new EventHandler(student2.DoTest);
  12:              teacher.TestEvent += new EventHandler(student3.DoTest);
  13:   
  14:              
  15:              teacher.Test();
  16:              Console.WriteLine("老师:考试结束");
  17:              Console.ReadKey();
  18:          }
  19:      }   

□ 结果        

1

□ 可见

不管学生的答题速度如何,都是按学生编号顺序交试卷,显然不合理。

  使用EventHandler的BeginInvoke()方式实现异步执行订阅者方法

修改老师的类,让老师用异步方法来触发订阅者方法。

   1:      public class Teacher
   2:      {
   3:          public event EventHandler TestEvent;
   4:   
   5:          public void Test()
   6:          {
   7:              Console.WriteLine("老师:同学们,现在开始考试");
   8:   
   9:              if (TestEvent != null)
  10:              {
  11:                  Delegate[] delArray = TestEvent.GetInvocationList(); //获取事件的委托链表
  12:                  foreach (Delegate del in delArray)
  13:                  {
  14:                      EventHandler method = (EventHandler)del;
  15:                      method.BeginInvoke(null, EventArgs.Empty, null, null);
  16:                  }
  17:              }
  18:          }
  19:      }

结果:
2

可见:
● 当异步执行订阅者方法的时候,客户端程序不会等到所有订阅者方法执行完成才进行,而是不理会订阅者的异步方法执行结果。
● 当异步执行订阅者方法的时候,最先执行完的先返回结果。
● BeginInvoke()是事件的方法,不是Delegate的方法,只能把委托链表中的委托向下转换成事件,再让事件执行异步方法。

原文地址:https://www.cnblogs.com/darrenji/p/3618547.html