成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

漫談C#開發中的事件與委托機制

開發 后端
今天我們將談到的是C#開發中的事件與委托機制,C#中的“事件”是當對象發生某些事情時,類向該類的客戶提供通知的一種方法。希望這些能給大家一些幫助。

概述

C#中的委托類似于C或C++中的函數指針。使用委托使程序員可以將方法引用封裝在委托對象內。然后可以將該委托對象傳遞給可調用所引用方法的代碼,而不必在編譯時知道將調用哪個方法。與C或C++中的函數指針不同,委托是面向對象,而且是類型安全的。

C#中的“事件”是當對象發生某些事情時,類向該類的客戶提供通知的一種方法。事件最常見的用途是用于圖形用戶界面;通常,表示界面中的控件的類具有一些事件,當用戶對控件進行某些操作(如單擊某個按鈕)時,將通知這些事件。

使用委托來聲明事件。委托對象封裝一個方法,以便可以匿名調用該方法。事件是類允許客戶為其提供方法(事件發生時應調用這些方法)的委托的一種方法。事件發生時,將調用其客戶提供給它的委托。

注明:委托是對方法的包裝 在不確定要調用什么方法時候而又不能用抽象或者多態實現的時候用委托。 

  1. public interface PilotLamp    
  2.  {    
  3. /// <summary>    
  4. /// green light    
  5. /// </summary>    
  6. void TurnOn();    
  7.  /// <summary>    
  8.  /// notice    
  9.  /// </summary>    
  10.  string Notice    
  11.  {    
  12.  get;    
  13. set;    
  14.  }    
  15.  }  

先創建PilotLamp.cs

再創建DelegateEvent.cs:

  1. public delegate void EventHandler();  

再創建TrafficLight.cs: 

  1. public class TrafficLight : PilotLamp    
  2.  {    
  3.  public event EventHandler Notices;    
  4. private string notice;    
  5. #region GreenLight 成員    
  6.  public void TurnOn()    
  7.  {    
  8.  if (Notices != null)    
  9.  Notices();    
  10.  }    
  11.  public string Notice    
  12.  {    
  13. get   
  14.  {    
  15.  return notice;    
  16.  }    
  17. set   
  18.  {    
  19.  notice = value;    
  20.  }    
  21.  }    
  22. #endregion    
  23.  }  

再創建Driver.cs

  1. public class Driver    
  2.     
  3. private string Name;    
  4. private PilotLamp greenLight;    
  5. public Driver(string name, PilotLamp greenLight)    
  6. {    
  7. this.Name = name;    
  8. this.greenLight = greenLight;    
  9. }    
  10. public void GoLeft()    
  11. {    
  12. Console.WriteLine(string.Format("{1}司機,{0},請向左開車.", greenLight.Notice, Name));    
  13. }    
  14. }  

再創建Pedestrian.cs: 

  1.  public class Pedestrian    
  2.  {    
  3.  private string Name;    
  4. private PilotLamp greenLight;    
  5. public Pedestrian(string name, PilotLamp greenLight)    
  6. {    
  7.  this.Name = name;    
  8.  this.greenLight = greenLight;    
  9.  }    
  10. public void GoThrough()    
  11.  {    
  12.  Console.WriteLine( string.Format("{0}同志,{1},請向前走.", Name, greenLight.Notice));    
  13.  }    
  14.  }  

***再調用:

  1.  public partial class Run : Form    
  2. {    
  3. public Run()    
  4.  {    
  5.  InitializeComponent();    
  6. }    
  7. private void btnRun_Click(object sender, EventArgs e)    
  8.  {    
  9. //-------------------------------------    
  10. TrafficLight trafficLight = new TrafficLight();    
  11.  Driver driverOne = new Driver("張三", trafficLight);    
  12. Driver driverTwo = new Driver("李四", trafficLight);    
  13. Pedestrian pedestrianOne = new Pedestrian("王五", trafficLight);    
  14.  Pedestrian pedestrianTwo = new Pedestrian("麻六", trafficLight);    
  15.  trafficLight.Notices += new Observer.EventHandler(driverOne.GoLeft);    
  16.  trafficLight.Notices += new Observer.EventHandler(driverTwo.GoLeft);    
  17.  trafficLight.Notices += new Observer.EventHandler(pedestrianOne.GoThrough);    
  18. trafficLight.Notices += new Observer.EventHandler(pedestrianTwo.GoThrough);    
  19.  trafficLight.Notice = "綠燈亮了.";    
  20.  trafficLight.TurnOn();    
  21. //-------------------------------------    
  22.  }    
  23.  }  

輸出時選控制臺應用程序如圖:

image

結果如下圖:

image

事件的使用示例: 

  1.  namespace DelegateAndEvent    
  2.  {    
  3.  class Program    
  4.  {    
  5.  static void Main(string[] args)    
  6. {    
  7. Publishser pub = new Publishser();    
  8. OneScriber oneSub = new OneScriber();    
  9.  TwoScriber twoSub = new TwoScriber();    
  10. ThreeScriber threeSub = new ThreeScriber ();    
  11.  pub.NumberChanged += new GeneralEventHandler(oneSub.OnNumberChanged);    
  12.  pub.NumberChanged += new GeneralEventHandler(twoSub.OnNumberChanged);    
  13.  pub.NumberChanged += new GeneralEventHandler(threeSub.OnNumberChanged);    
  14. pub.DoSomething();    
  15. }    
  16.  }    
  17.  public delegate string GeneralEventHandler();    
  18.  public class Publishser    
  19.  {    
  20.  public event GeneralEventHandler NumberChanged;    
  21. public void DoSomething()    
  22. {    
  23.  if (NumberChanged != null)    
  24.  {    
  25.  Delegate[] generalEventHandlers = NumberChanged.GetInvocationList();    
  26. foreach (Delegate generalEventHandler in generalEventHandlers)    
  27.  {    
  28. GeneralEventHandler mothed = (GeneralEventHandler)generalEventHandler;    
  29.  string rtn = mothed();    
  30.  Console.WriteLine(rtn);    
  31.  System.Threading.Thread.Sleep(2000);    
  32.  }    
  33.  }    
  34.  }    
  35.  }    
  36.  public class OneScriber    
  37.  {    
  38.  public string OnNumberChanged()    
  39.  {    
  40.  return "One Subscriber";    
  41.  }    
  42.  }    
  43.  public class TwoScriber    
  44.  {    
  45.  public string OnNumberChanged()    
  46.  {    
  47.  return "Two Subscriber";    
  48. }    
  49.  }    
  50.  public class ThreeScriber    
  51.  {    
  52.  public string OnNumberChanged()    
  53.  {    
  54.  return "Three Subscriber";    
  55.  }    
  56.  }    
  57.  }  

運行結果:

image

注意到Delegate是GeneralEventHandler 的基類,所以為了觸發事件,先要進行一個向下的強制轉換,之后才能在其上觸發事件,調用所有注冊對象的方法。除了使用這種方式以外,還有一種更靈活方式可以調用方法,它是定義在Delegate基類中的DynamicInvoke()方法:

 

  1. public object DynamicInvoke(params object[] args); 

這可能是調用委托最通用的方法了,適用于所有類型的委托。它接受的參數為object[],也就是說它可以將任意數量的任意類型作為參數,并返回單個object對象。上面的DoSomething()方法也可以改寫成下面這種通用形式:

代碼作如下改動:

  1. namespace DelegateAndEvent    
  2. {    
  3.  class Program    
  4.  {    
  5.  static void Main(string[] args)    
  6. {    
  7.  Publishser pub = new Publishser();    
  8. OneScriber oneSub = new OneScriber();    
  9.  TwoScriber twoSub = new TwoScriber();    
  10.  ThreeScriber threeSub = new ThreeScriber();    
  11.  pub.NumberChanged += new GeneralEventHandler(oneSub.OnNumberChanged);    
  12.  pub.NumberChanged += new GeneralEventHandler(twoSub.OnNumberChanged);    
  13. pub.NumberChanged += new GeneralEventHandler(threeSub.OnNumberChanged);    
  14.  List<string> strlist = pub.DoSomething();    
  15. foreach (string result in strlist)    
  16.  Console.WriteLine(result);    
  17.  System.Threading.Thread.Sleep(5000);    
  18.  }    
  19.  }    
  20. public delegate string GeneralEventHandler();    
  21.  public class Publishser    
  22. {    
  23. public event GeneralEventHandler NumberChanged;    
  24.  public List<string> DoSomething()    
  25.  {    
  26.  List<string> strList = new List<string>();    
  27. if (NumberChanged == nullreturn strList;    
  28.  Delegate[] generalEventHandlers = NumberChanged.GetInvocationList();    
  29.  foreach (Delegate generalEventHandler in generalEventHandlers)    
  30. {    
  31.  // GeneralEventHandler mothed = (GeneralEventHandler)generalEventHandler;    
  32.  string rtn = generalEventHandler.DynamicInvoke(null).ToString();    
  33.  strList.Add(rtn);    
  34. }    
  35. return strList;    
  36. }    
  37.  }    
  38.  public class OneScriber    
  39. {    
  40.  public string OnNumberChanged()    
  41. {    
  42.  return "One Subscriber";    
  43.  }    
  44.  }    
  45.  public class TwoScriber    
  46.  {    
  47.  public string OnNumberChanged()    
  48.  {    
  49.  return "Two Subscriber";    
  50.  }    
  51.  }    
  52.  public class ThreeScriber    
  53.  {    
  54. public string OnNumberChanged()    
  55.  {    
  56. return "Three Subscriber";    
  57.  }    
  58.  }    
  59.  }  

結果如下:

image

還是一樣的結果.

委托的定義會生成繼承自MulticastDelegate的完整的類,其中包含Invoke()、BeginInvoke()和EndInvoke()方法。當我們直接調用委托時,實際上是調用了Invoke()方法,它會中斷調用它的客戶端,然后在客戶端線程上執行所有訂閱者的方法(客戶端無法繼續執行后面代碼),***將控制權返回客戶端。注意到BeginInvoke()、EndInvoke()方法,在.Net中,異步執行的方法通常都會配對出現,并且以Begin和End作為方法的開頭(最常見的可能就是Stream類的BeginRead()和EndRead()方法了)。它們用于方法的異步執行,即是在調用BeginInvoke()之后,客戶端從線程池中抓取一個閑置線程,然后交由這個線程去執行訂閱者的方法,而客戶端線程則可以繼續執行下面的代碼。

BeginInvoke()接受“動態”的參數個數和類型,為什么說“動態”的呢?因為它的參數是在編譯時根據委托的定義動態生成的,其中前面參數的個數和類型與委托定義中接受的參數個數和類型相同,***兩個參數分別是AsyncCallback和Object類型,對于它們更具體的內容,可以參見下一節委托和方法的異步調用部分。現在,我們僅需要對這兩個參數傳入null就可以了。另外還需要注意幾點:

在委托類型上調用BeginInvoke()時,此委托對象只能包含一個目標方法,所以對于多個訂閱者注冊的情況,必須使用GetInvocationList()獲得所有委托對象,然后遍歷它們,分別在其上調用BeginInvoke()方法。如果直接在委托上調用BeginInvoke(),會拋出異常,提示“委托只能包含一個目標方法”。

如果訂閱者的方法拋出異常,.NET會捕捉到它,但是只有在調用EndInvoke()的時候,才會將異常重新拋出。而在本例中,我們不使用EndInvoke()(因為我們不關心訂閱者的執行情況),所以我們無需處理異常,因為即使拋出異常,也是在另一個線程上,不會影響到客戶端線程(客戶端甚至不知道訂閱者發生了異常,這有時是好事有時是壞事)

BeginInvoke()方法屬于委托定義所生成的類,它既不屬于MulticastDelegate也不屬于Delegate基類, 我們需要進行一個向下轉換,來獲取到實際的委托類型。

示例:

  1. namespace DelegateAndEvent    
  2.  {    
  3.  class Program    
  4.  {    
  5.  static void Main(string[] args)    
  6.  {    
  7.  Publishser pub = new Publishser();    
  8.  OneScriber oneSub = new OneScriber();    
  9. TwoScriber twoSub = new TwoScriber();    
  10.  ThreeScriber threeSub = new ThreeScriber();    
  11.  pub.NumberChanged += new GeneralEventHandler(oneSub.OnNumberChanged);    
  12.  pub.NumberChanged += new GeneralEventHandler(twoSub.OnNumberChanged);    
  13.  pub.NumberChanged += new GeneralEventHandler(threeSub.OnNumberChanged);    
  14. List<string> strlist = pub.DoSomething();    
  15.  foreach (string result in strlist)    
  16. Console.WriteLine(result);    
  17.  System.Threading.Thread.Sleep(5000);    
  18.  }    
  19. }    
  20.  public delegate string GeneralEventHandler(object sender,EventArgs e);    
  21.  public class Publishser    
  22.  {    
  23. public event GeneralEventHandler NumberChanged;    
  24. public List<string> DoSomething()    
  25.  {    
  26. List<string> strList = new List<string>();    
  27. if (NumberChanged == nullreturn strList;    
  28.  Delegate[] generalEventHandlers = NumberChanged.GetInvocationList();    
  29.  foreach (Delegate generalEventHandler in generalEventHandlers)    
  30.  {    
  31.  GeneralEventHandler mothed = (GeneralEventHandler)generalEventHandler;    
  32.  IAsyncResult result = mothed.BeginInvoke(this, EventArgs.Empty, nullnull);    
  33. string str = mothed.EndInvoke(result);    
  34.  strList.Add(str);    
  35. }    
  36.  return strList;    
  37. }    
  38.  }    
  39.  public class OneScriber    
  40.  {    
  41. public string OnNumberChanged(object sender,EventArgs e)    
  42. {    
  43.  return "One Subscriber";    
  44.  }    
  45. }    
  46.  public class TwoScriber    
  47.  {    
  48. public string OnNumberChanged(object sender, EventArgs e)    
  49.  {    
  50. return "Two Subscriber";    
  51.  }    
  52.  }    
  53.  public class ThreeScriber    
  54.  {    
  55. public string OnNumberChanged(object sender, EventArgs e)    
  56. {    
  57.  return "Three Subscriber";    
  58. }    
  59.  }    
  60.  }  

結果:

image

BeginInvoke的另外兩個參數分別是AsyncCallback和Object類型,其中AsyncCallback是一個委托類型,它用于方法的回調,即是說當異步方法執行完畢時自動進行調用的方法。它的定義為:

public delegate void AsyncCallback(IAsyncResult ar);

Object類型用于傳遞任何你想要的數值,它可以通過IAsyncResult的AsyncState屬性獲得。

原文鏈接:http://www.cnblogs.com/springyangwc/archive/2011/06/20/2085541.html

【編輯推薦】

  1. 漫談C#開發中的反射機制
  2. 漫談C#開發中的ASP.NET頁生命周期
  3. 淺析C#延遲加載的運行機制和應用場景
  4. C#多線程中lock的用法
  5. 用C#實現HTTP協議下的多線程文件傳輸

 

責任編輯:彭凡 來源: 博客園
相關推薦

2024-05-16 13:36:04

C#委托事件

2011-06-08 10:06:32

C#

2024-05-15 09:11:51

委托事件C#

2011-06-28 10:19:40

C#開發

2009-08-03 13:23:04

C#編程組件-事件-委托

2024-06-28 10:19:02

委托事件C#

2024-06-25 08:43:25

C#編程模型

2009-08-18 10:54:17

C#事件和委托

2009-08-27 16:53:01

C#委托C#事件

2009-08-26 14:48:05

C#委托與事件

2009-10-09 09:07:40

C#委托和事件

2009-08-26 14:27:54

C#委托和事件

2009-08-04 13:53:58

C#委托類C#事件

2009-08-18 11:08:24

.Net Framew

2024-10-05 00:00:35

Action?C#Func?

2024-05-30 12:24:03

C#開發

2024-12-23 08:00:00

委托C#編程

2024-09-29 09:28:38

Action?C#

2011-06-22 10:04:03

C#開發

2011-06-21 10:26:37

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产青草久久久久福利 | 亚洲精品视频一区二区三区 | 国产成人福利在线 | 在线国产一区二区 | 亚洲一级毛片 | 欧美日本一区 | 91久色 | 久久久久久91 | 国产99视频精品免费播放照片 | 91视频一88av | 精精国产xxxx视频在线播放 | 免费在线观看av网址 | 日韩一区二区在线视频 | 国产一区三区在线 | 亚洲国产成人av好男人在线观看 | 成人a视频片观看免费 | 日本久久精 | 亚洲一区视频 | 中文字幕国产精品 | 中文字幕日韩专区 | 欧美群妇大交群中文字幕 | 久久人人网 | 国产精品麻 | 成人久久网 | 日韩欧美国产一区二区 | 久久国产婷婷国产香蕉 | 毛片a | 精品久久久久久亚洲精品 | 国产精品高潮呻吟久久久久 | 一区二区三区四区免费在线观看 | 综合色导航 | 成人国产一区二区三区精品麻豆 | 欧美精品1区2区 | 久久69精品久久久久久国产越南 | 午夜影院在线 | 国内精品一区二区 | 日韩和的一区二在线 | 欧美精品一区二区三区在线播放 | 日韩精品成人免费观看视频 | 日本成人中文字幕 | 黄色网络在线观看 |