1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace _05委托_事件与Observer设计模式 8 { 9 public delegate void HeateEventHandler(int temp);10 public class Heater11 {12 //定义一个私有字段13 private int temperature;14 public event HeateEventHandler heate;15 public void HeateOnEvent()16 {17 for (int i = 0; i <= 100;i++ )18 {19 temperature = i;20 if(i>96)21 {22 if(heate!=null)23 {24 heate(temperature);25 Thread.Sleep(5000);26 }27 }28 }29 }30 31 }32 public class Alarm33 {34 public void MakeAlarm(int temp)35 {36 Console.WriteLine("警报:当前水温{0}度",temp);37 }38 }39 public class Display40 {41 public static void ShowDisplay(int temp)42 {43 Console.WriteLine("显示:水快烧开了,当前温度为{0}",temp);44 }45 }46 class Program47 {48 static void Main(string[] args)49 {50 Heater he = new Heater();51 Alarm al = new Alarm();52 he.heate += al.MakeAlarm;53 //给匿名对象注册方法54 //he.heate+=(new Alarm).MakeAlarm;55 he.heate += Display.ShowDisplay;56 he.HeateOnEvent();57 Console.ReadLine();58 }59 #region//总结一下-Observer设计模式60 /*概念:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变 时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。61 * 1、什么是耦合?什么是松耦合?什么是紧耦合?62 解释:耦合就是依赖的程度。松耦合就是依赖程度不强,紧耦合就是依赖程度很强。网上找了个63 形象的解释:假如你去麦当劳前台买可乐, 你可以把你和麦当劳工作人员想象为软件的两层或两 个模块.那么你给服务员5块钱,然后他帮你打一杯可乐,你们之间是松耦合的,你们的接口就是5块 钱,你只要给他钱,就不用管他是怎么拿杯子,从哪打的可乐.但是如果你给他5块钱,然后你要自己 去取杯子,去找可乐机,自己排队, 那么你跟麦当劳就是紧密耦合的.64 * 2、Observer设计模式中主要包括两类对象:Subject(监视对象,包含监视者感兴趣的东西)和 Observer(监视者,当监视的对象中某个事件发生时,监视者就采取行动)。本例中Heate是监视对 象,Alarm和Dispaly是监视者,感兴趣的东西就是温度,当温度超过某一临界值的时候,监视对 象将监视者感兴趣的东西传给监视者,监视者采取行动。65 * 3、匿名对象:一个临时的对象。没有明确给出名字的对象,只在堆内存中开辟空间,在棧内存中没 有引用地址。66 */67 #endregion68 }69 }
06为什么要使用事件呢?
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _06为什么使用事件 7 { 8 //定义委托 9 public delegate void NumberChangedEventHandler(int count);10 //定义事件的发布者11 public class Publisher12 {13 //声明一个事件14 public event NumberChangedEventHandler NumberChanged;15 //声明一个委托变量16 //(1)public NumberChangedEventHandler NumberChanged;17 //声明触发事件的方法18 public void DoSomething()19 {20 for (int i = 0; i < 23; i++)21 {22 if (i == 8)23 {24 if (NumberChanged != null)25 {26 NumberChanged(i);27 }28 }29 }30 }31 }32 //定义事件的订阅者33 public class Subscriber34 {35 public void OnNumberChanged(int count)36 {37 Console.WriteLine("事件订阅者:{0}", count);38 }39 }40 class Program41 {42 static void Main(string[] args)43 {44 Subscriber sb = new Subscriber();45 Publisher pb = new Publisher();46 pb.NumberChanged += new NumberChangedEventHandler(sb.OnNumberChanged);47 pb.DoSomething();//事件的本意是当事件发布类中的某个行为触发时,引发事件,也就是说当触发事件的方法满足某个条件时触发事件。事件不应该由客户端触发,而是由事件的发布类的内部触发。这样写使事件的发布类的封装性更好。48 //(1)pb.NumberChanged(100);//定义一个委托变量,这里的NumberChanged不是事件49 Console.ReadLine();50 }51 }52 }
07让事件只允许一个客户端订阅
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _07让事件只允许一个客户端订阅 7 { 8 public delegate string GenneralEventHandler(); 9 public class Publisher10 {11 public event GenneralEventHandler NumberChanged;12 public void Register(GenneralEventHandler method)13 {14 //注意这里:此处注册事件采用的是方法,而不再用+=了15 NumberChanged=method;16 }17 public void UnRegister(GenneralEventHandler method)18 {19 NumberChanged-=method;20 }21 public void DoSomething()22 {23 if(NumberChanged!=null)24 {25 string rtn=NumberChanged();26 Console.WriteLine(rtn);27 }28 }29 }30 public class Subscriber131 {32 public string OnNumberChanged()33 {34 Console.WriteLine("subscriber1 invoke");35 return "subscriber1";36 }37 }38 public class Subscriber239 {40 public string OnNumberChanged()41 {42 Console.WriteLine("subscriber2 invoke");43 return "subscriber2";44 }45 }46 class Program47 {48 static void Main(string[] args)49 {50 Publisher pub = new Publisher();51 Subscriber1 sub1 = new Subscriber1();52 Subscriber2 sub2 = new Subscriber2();53 pub.Register(sub1.OnNumberChanged);54 pub.Register(sub2.OnNumberChanged);//输出的是subscriber255 //pub.UnRegister(sub2.OnNumberChanged);//将其注释去掉,输出为空56 pub.DoSomething();57 Console.ReadLine();58 }59 }60 }
08用事件访问器来实现只让一个用户端订阅
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _08用事件访问器来实现只让一个用户端订阅 7 { 8 public delegate string GeneralEventHandler(); 9 public class Publisher10 {11 private event GeneralEventHandler numberChanged;12 public event GeneralEventHandler Numberchanged13 {14 add15 {16 numberChanged = value;17 }18 remove19 {20 numberChanged -= value;21 }22 }23 public void DoSomething()24 { 25 if(numberChanged!=null)26 {27 string str = numberChanged();28 Console.WriteLine(str);29 }30 }31 }32 public class Subscriber133 {34 public string OnNumberChanged()35 {36 Console.WriteLine("subscriber1 invoke");37 return "subscriber1";38 }39 }40 public class Subscriber241 {42 public string OnNumberChanged()43 {44 Console.WriteLine("subscriber2 invoke");45 return "subscriber2";46 }47 }48 class Program49 {50 static void Main(string[] args)51 {52 Publisher pub = new Publisher();53 Subscriber1 sub1 = new Subscriber1();54 Subscriber2 sub2 = new Subscriber2();55 pub.Numberchanged += sub1.OnNumberChanged;56 pub.Numberchanged += sub2.OnNumberChanged;57 // pub.Numberchanged -= sub2.OnNumberChanged;58 pub.DoSomething();59 Console.ReadLine();60 }61 }62 }
09获得多个返回值与异常处理
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _09获得多个返回值与异常处理 7 { 8 public delegate string DemoEventHandler(int num); 9 public class Publisher10 {11 public event DemoEventHandler NumberChanged;12 public List DoSomething()13 {14 List strList = new List ();15 if(NumberChanged==null)16 {17 return strList;18 }19 Delegate[] delArray = NumberChanged.GetInvocationList();20 foreach(Delegate del in delArray)21 {22 DemoEventHandler method = (DemoEventHandler)del;//强制向下转换23 strList.Add(method(100));24 }25 return strList;26 }27 }28 public class Subscriber129 {30 public string OnNumberChanged(int num)31 {32 Console.WriteLine("subscriber1 invoke,number:{0}",num);33 return "[Subscriber1 returned]";34 }35 }36 public class Subscriber237 {38 public string OnNumberChanged(int num)39 {40 Console.WriteLine("subscriber2 invoke,number:{0}", num);41 return "[Subscriber2 returned]";42 }43 }44 public class Subscriber345 {46 public string OnNumberChanged(int num)47 {48 Console.WriteLine("subscriber3 invoke,number:{0}", num);49 return "[Subscriber3 returned]";50 }51 }52 class Program53 {54 static void Main(string[] args)55 {56 Publisher pub = new Publisher();57 Subscriber1 sub1 = new Subscriber1();58 Subscriber2 sub2 = new Subscriber2();59 Subscriber3 sub3 = new Subscriber3();60 pub.NumberChanged += new DemoEventHandler(sub1.OnNumberChanged);61 pub.NumberChanged += new DemoEventHandler(sub2.OnNumberChanged);62 pub.NumberChanged += new DemoEventHandler(sub3.OnNumberChanged);63 List list = pub.DoSomething();64 foreach (string item in list)65 {66 Console.WriteLine(item);67 }68 Console.ReadLine();69 }70 }71 }
10异常处理
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _10异常处理 7 { 8 public delegate void MyEventHandler(object sender,EventArgs e); 9 public class Publisher10 {11 public event MyEventHandler MyEvent;12 public void DoSomething()13 {14 if (MyEvent != null)15 {16 try17 {18 MyEvent(this,EventArgs.Empty);19 }20 catch(Exception e)21 {22 Console.WriteLine("Exception:{0}",e.Message);23 }24 }25 }26 }27 public class Subscriber128 {29 public void OnEvent(object sender,EventArgs e) 30 {31 Console.WriteLine("Subscriber1 Invoked !");32 }33 }34 public class Subscriber235 {36 public void OnEvent(object sender,EventArgs e)37 {38 throw new Exception("Exception2 Failed");39 //捕获异常,使得程序没有异常结束,但是却影响到了后面的订阅者的执行40 }41 }42 public class Subscriber343 {44 public void OnEvent(object sender,EventArgs e)45 {46 Console.WriteLine("Subscriber3 Invoked!");47 }48 }49 class Program50 {51 static void Main(string [] args)52 {53 Publisher pub = new Publisher();54 Subscriber1 sub1 = new Subscriber1();55 Subscriber2 sub2 = new Subscriber2();56 Subscriber3 sub3 = new Subscriber3();57 pub.MyEvent += new MyEventHandler(sub1.OnEvent);58 pub.MyEvent += new MyEventHandler(sub2.OnEvent);59 pub.MyEvent += new MyEventHandler(sub3.OnEvent);60 pub.DoSomething();61 Console.ReadKey();62 }63 }64 65 }
10异常处理02
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _10异常处理02 7 { 8 public delegate void MyEventHandler(object sender, EventArgs e); 9 public class Publisher10 {11 public event MyEventHandler MyEvent;12 public void DoSomething()13 {14 if (MyEvent != null)15 {16 Delegate[] delArray = MyEvent.GetInvocationList();17 foreach (Delegate del in delArray)18 {19 try20 {21 del.DynamicInvoke(this,EventArgs.Empty);22 }23 catch(Exception e)24 {25 Console.WriteLine("Exception:{0}",e.Message);26 }27 }28 }29 }30 }31 public class Subscriber132 {33 public void OnEvent(object sender, EventArgs e)34 {35 Console.WriteLine("Subscriber1 Invoked !");36 }37 }38 public class Subscriber239 {40 public void OnEvent(object sender, EventArgs e)41 {42 throw new Exception("Exception2 Failed");43 //捕获异常,使得程序没有异常结束,但是却影响到了后面的订阅者的执行44 }45 }46 public class Subscriber347 {48 public void OnEvent(object sender, EventArgs e)49 {50 Console.WriteLine("Subscriber3 Invoked!");51 }52 }53 class Program54 {55 static void Main(string[] args)56 {57 Publisher pub = new Publisher();58 Subscriber1 sub1 = new Subscriber1();59 Subscriber2 sub2 = new Subscriber2();60 Subscriber3 sub3 = new Subscriber3();61 pub.MyEvent += new MyEventHandler(sub1.OnEvent);62 pub.MyEvent += new MyEventHandler(sub2.OnEvent);63 pub.MyEvent += new MyEventHandler(sub3.OnEvent);64 pub.DoSomething();65 Console.ReadKey();66 }67 }68 }
10异常处理03
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _10异常处理03 7 { 8 public delegate void MyEventHandler(object sender,EventArgs e); 9 public class Publisher10 {11 public event MyEventHandler MyEvent;12 public void DoSomething()13 {14 Publisher.FireEvent(MyEvent,this,EventArgs.Empty);15 }16 public static object[]FireEvent(Delegate del,params object[]args)17 {18 List
11委托中订阅者方法的超时处理
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace _11委托中订阅者方法的超时处理 8 { 9 public delegate void MyEventHandler(object sender,EventArgs e);10 public class Publisher11 {12 public event MyEventHandler MyEvent;13 public void DoSomething()14 {15 Console.WriteLine("DoSomething invoke !");16 Program.FireEvent(MyEvent,this,EventArgs.Empty);17 }18 }19 public class Subscriber120 {21 public void OnEvent(object sender,EventArgs e)22 {23 Thread.Sleep(TimeSpan.FromSeconds(3));24 Console.WriteLine("Wait for 3 seconds ,subscriber1 invoked !");25 }26 27 }28 public class Subscriber229 {30 public void OnEvent(object sender,EventArgs e)31 {32 Console.WriteLine("Subscriber2 is Invoked !");33 }34 }35 public class Subscriber336 {37 public void OnEvent(object sender,EventArgs e)38 {39 Thread.Sleep(TimeSpan.FromSeconds(2));40 Console.WriteLine("Wait for 2 seconds ,subscriber2 invoked !");41 }42 }43 class Program44 {45 static void Main(string[] args)46 {47 //初始化对象48 Publisher pub = new Publisher();49 Subscriber1 sub1 = new Subscriber1();50 Subscriber2 sub2 = new Subscriber2();51 Subscriber3 sub3 = new Subscriber3();52 //初始化事件53 pub.MyEvent += new MyEventHandler(sub1.OnEvent);54 pub.MyEvent += new MyEventHandler(sub2.OnEvent);55 pub.MyEvent += new MyEventHandler(sub3.OnEvent);56 //调用触发事件的方法57 pub.DoSomething();58 Console.WriteLine("返回控制权");59 Console.ReadLine();60 }61 public static object[] FireEvent(Delegate del,params object[]args)62 {63 List objList = new List();64 if(del!=null)65 {66 Delegate[] delArray = del.GetInvocationList();67 foreach(Delegate method in delArray)68 {69 try70 {71 object obj = method.DynamicInvoke(args);72 if (obj != null)73 {74 objList.Add(obj);75 }76 }77 catch { }78 }79 }80 return objList.ToArray();81 }82 }83 #region//总结一下84 /*85 * 1、在依次执行订阅者方法时,当前线程会转去执行方法中的代码,调用方法的客户端会被中断,86 * 只有当方法全部执行完毕之后,控制权才回到客户端手里。87 * 2、事件的发布者并不关心谁订阅了事件,也不关心订阅者的方法有没有返回值,它只需要在事件88 * 发生的瞬间告知订阅者事件已经发生并将相关的参数传给订阅者就可以了,然后继续执行它后89 * 面的代码,而不是等待订阅者完成后再执行后面的代码。90 */91 #endregion92 }
11委托中订阅者方法的超时处理02
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace _11委托中订阅者方法的超时处理02 8 { 9 //public delegate void MyEventHandler(object sender,EventArgs e);10 public class Publisher11 {12 public event EventHandler MyEvent;13 public void DoSomething()14 {15 Console.WriteLine("DoSomething Invoke !");16 if (MyEvent != null)17 {18 Delegate[] delArray = MyEvent.GetInvocationList();19 foreach (Delegate del in delArray)20 {21 try22 {23 EventHandler method = (EventHandler)del;24 method.BeginInvoke(null, EventArgs.Empty, null, null);25 //对于多个订阅者注册的情况,必须使用GetInvocationList()获得所有委托对象,26 ///然后遍历它们,分别在其上调用BeginInvoke()方法27 }28 catch(Exception e)29 {30 Console.WriteLine(e.Message);31 }32 33 }34 }35 }36 }37 public class Subscriber138 {39 public void OnEvent(object sender, EventArgs e)40 {41 Thread.Sleep(TimeSpan.FromSeconds(3));42 Console.WriteLine("Subscriber1 Invoked ! 延迟3秒");43 }44 }45 public class Subscriber246 {47 public void OnEvent(object sender, EventArgs e)48 {49 throw new Exception("Subscriber2 failed !");50 }51 }52 public class Subscriber353 {54 public void OnEvent(object sender, EventArgs e)55 {56 Thread.Sleep(TimeSpan.FromSeconds(2));57 Console.WriteLine("Subscriber3 Invoked !延迟2秒");58 }59 }60 class Program61 {62 static void Main(string[] args)63 {64 //初始化对象65 Publisher pub = new Publisher();66 Subscriber1 sub1 = new Subscriber1();67 Subscriber2 sub2 = new Subscriber2();68 Subscriber3 sub3 = new Subscriber3();69 //初始化事件70 pub.MyEvent += new EventHandler(sub1.OnEvent);71 pub.MyEvent += new EventHandler(sub2.OnEvent);72 pub.MyEvent += new EventHandler(sub3.OnEvent);73 //调用触发事件的方法74 pub.DoSomething();75 Console.WriteLine("返回控制权");76 Console.WriteLine("press any key to exit");77 Console.ReadLine();78 79 #region80 /*81 * 1、当我们直接调用委托时,实际上是调用了Invoke()方法,它会中断调用它的客户端,然后在82 * 客户端程序上执行所有订阅者的方法,最后将控制权返回客户端83 * 2、客户端所在的线程通常是主线程,而执行订阅者方法的线程来自线程池,属于后台线程,当84 * 主线程结束时,不论后台线程有没有结束,都会退出程序。85 * 3、本次订阅者中一个停留3秒,一个停留两秒,实际上这两个方法是并行执行的,也就是说最长86 * 的是3秒。87 */88 #endregion89 }90 }91 }
12委托和方法的异步调用
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace _12委托和方法的异步调用 8 { 9 class Program10 {11 static void Main(string[] args)12 {13 Console.WriteLine("Client application started !");14 Thread.CurrentThread.Name = "Main Thread";15 16 Calculator cal = new Calculator();17 int result = cal.Add(2,5);18 Console.WriteLine("Result:{0}",result);19 for (int i = 1; i <= 3;i++ )20 {21 Thread.Sleep(TimeSpan.FromSeconds(i));22 Console.WriteLine("{0}:Client executed{1}seconds",Thread.CurrentThread.Name,i);23 }24 Console.ReadLine();25 }26 }27 public class Calculator28 { 29 public int Add(int x,int y)30 {31 if(Thread.CurrentThread.IsThreadPoolThread==true)32 {33 Thread.CurrentThread.Name = "Pool Thread";34 }35 Console.WriteLine("Method invoked!");36 for (int i = 1; i <= 2;i++ )37 {38 Thread.Sleep(TimeSpan.FromSeconds(i));39 Console.WriteLine("{0}:Add executed{1}seconds.",Thread.CurrentThread.Name,i);40 }41 Console.WriteLine("Method complete !");42 return x + y;43 }44 }45 }
12委托和方法的异步调用02
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace _12委托和方法的异步调用02 8 { 9 public delegate int AddDelegate(int x,int y);10 public class Calculator11 {12 public int Add(int x,int y)13 {14 if(Thread.CurrentThread.IsThreadPoolThread==true)15 {16 Thread.CurrentThread.Name = "线程池";17 }18 //延缓两秒钟19 for (int i = 1; i <= 2;i++ )20 {21 Thread.Sleep(TimeSpan.FromSeconds(i));22 Console.WriteLine("{0}:延缓{1}秒",Thread.CurrentThread.Name,i);23 }24 Console.WriteLine("方法执行完毕");25 return x + y;26 }27 }28 class Program29 {30 static void Main(string[] args)31 {32 Console.WriteLine("客户端应用程序开始执行");33 Thread.CurrentThread.Name = "主线程";34 35 Calculator cal = new Calculator();36 AddDelegate del = new AddDelegate(cal.Add);37 IAsyncResult asr=del.BeginInvoke(2,3,null,null);38 //模拟3秒钟39 for (int i = 1; i <= 3;i++ )40 {41 Thread.Sleep(TimeSpan.FromSeconds(i));42 Console.WriteLine("{0}:客户端线程停留{1}",Thread.CurrentThread.Name,i);43 }44 int result = del.EndInvoke(asr);45 Console.WriteLine("结果:{0}",result);46 Console.WriteLine("结束");47 48 Console.ReadLine();49 }50 }51 }