欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何理解.Net事件

今天就跟大家聊聊有關如何理解.Net事件,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

創(chuàng)新互聯(lián)主營平魯網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,成都app軟件開發(fā)公司,平魯h5小程序制作搭建,平魯網(wǎng)站營銷推廣歡迎平魯?shù)鹊貐^(qū)企業(yè)咨詢

.NET 事件

事件概述

在發(fā)生其他類或?qū)ο箨P注的事情時,類或?qū)ο罂赏ㄟ^事件通知它們。發(fā)送(或引發(fā))事件的類稱為“發(fā)行者”,接收(或處理)事件的類稱為“訂戶”。

  • 特點

    • 發(fā)行者確定何時引發(fā)事件,訂戶確定執(zhí)行何種操作來響應該事件。

    • 一個事件可以有多個訂戶。一個訂戶可處理來自多個發(fā)行者的多個事件。

    • 沒有訂戶的事件永遠不會被調(diào)用。

    • 事件通常用于通知用戶操作

    • 如果一個事件有多個訂戶,當引發(fā)該事件時,會同步調(diào)用多個事件處理程序,也可以設置異步調(diào)用事件。

    • 可以利用事件同步線程。

    • 事件是基于 EventHandler 委托和 EventArgs 基類的。

事件的訂閱和取消

如果您想編寫引發(fā)事件時調(diào)用的自定義代碼,則可以訂閱由其他類發(fā)布的事件。例如,可以訂閱某個按鈕的“單擊”事件,以使應用程序在用戶單擊該按鈕時執(zhí)行一些有用的操作。

  • 訂閱事件

    • 如果“屬性”窗口不可見,請在“設計”視圖中,右擊要創(chuàng)建事件處理程序的窗體或控件,然后選擇“屬性”。

    • 在“屬性”窗口的頂部,單擊“事件”圖標。

    • 雙擊要創(chuàng)建的事件,Visual C#  會創(chuàng)建一個空事件處理程序方法,并將其添加到您的代碼中。或者,您也可以在“代碼”視圖中手動添加代碼。

    • VS IDE 訂閱事件

  • 編程方式訂閱事件

    • 定義一個事件處理程序方法,其簽名與該事件的委托簽名匹配。例如,如果事件基于  EventHandler 委托類型,則下面的代碼表示方法存根


    • 使用加法賦值運算符 (+=) 來為事件附加事件處理程序。在下面的示例中,假設名為 publisher  的對象擁有一個名為 RaiseCustomEvent 的事件。請注意,訂戶類需要引用發(fā)行者類才能訂閱其事件。

    1. oid HandleCustomEvent(object sender, CustomEventArgs a){  } 

publisher.RaiseCustomEvent += HandleCustomEvent; publisher.RaiseCustomEvent += new CustomEventHandler(HandleCustomEvent);
  • 匿名方法訂閱事件

    • 使用加法賦值運算符 (+=) 來為事件附加匿名方法。在下面的示例中,假設名為  publisher 的對象擁有一個名為 RaiseCustomEvent 的事件,并且還定義了一個 CustomEventArgs  類以承載某些類型的專用事件信息。請注意,訂戶類需要引用 publisher 才能訂閱其事件。

  1. publisher.RaiseCustomEvent += delegate(object o, CustomEventArgs e) 

  2.     string s = o.ToString() + " " + e.ToString(); 

  3.     Console.WriteLine(s); 

  4. };

  • 取消訂閱

要防止在引發(fā)事件時調(diào)用事件處理程序,您只需取消訂閱該事件。要防止資源泄露,請在釋放訂戶對象之前取消訂閱事件,這一點很重要。在取消訂閱事件之前,在發(fā)布對象中作為該事件的基礎的多路廣播委托會引用封裝了訂戶的事件處理程序的委托。只要發(fā)布對象包含該引用,就不會對訂戶對象執(zhí)行垃圾回收。

使用減法賦值運算符 (-=)  取消訂閱事件。所有訂戶都取消訂閱某事件后,發(fā)行者類中的事件實例會設置為 null。

publisher.RaiseCustomEvent -= HandleCustomEvent;

發(fā)布標準事件

下面的過程演示了如何將符合標準 .NET Framework 模式的事件添加到您自己的類和結(jié)構(gòu)中。.NET Framework 類庫中的所有事件均基于  EventHandler 委托,定義如下。

  1. public delegate void EventHandler(object sender, EventArgs e);

  • 采用 EventHandler  模式發(fā)布事件

    • 如果沒有自定義 EventArgs 類,事件類型就是非泛型 EventHandler  委托。它無需聲明,因為它已在 C# 項目默認包含的 System 命名空間中進行了聲明

    •  


    • 如果使用的是 EventHandler 的非泛型版本,并且您有一個由 EventArgs  派生的自定義類,請在發(fā)布類中聲明您的事件,并且將您的委托用作類型

    •  


    • 如果使用的是泛型版本,則不需要自定義委托。相反,應將事件類型指定為  EventHandler<CustomEventArgs>,在尖括號內(nèi)放置您自己的類的名稱。


    • (如果不需要發(fā)送含事件的自定義數(shù)據(jù),請?zhí)^此步驟,直接進入步驟  3。)在發(fā)行者類和訂戶類均可看見的范圍中聲明類,并添加保留自定義事件數(shù)據(jù)所需的成員。在此示例中,會返回一個簡單字符串。

    •  


    • (如果您使用的是 EventHandler  的泛型版本,請?zhí)^此步驟。)在發(fā)布類中聲明一個委托。為它指定以 EventHandler 結(jié)尾的名稱。第二個參數(shù)指定自定義 EventArgs  類型。

    •  


    • 使用以下任一步驟,在發(fā)布類中聲明事件。

    1. public event EventHandler RaiseCustomEvent; 

    1. class Publisher 

    2.     public event CustomEventHandler RaiseCustomEvent; 

    1. public event EventHandler<CustomEventArgs> RaiseCustomEvent; 

    1. public delegate void CustomEventHandler(object sender, CustomEventArgs a); 

    1. public class CustomEventArgs : EventArgs 

    2.     public CustomEventArgs(string s) 

    3.     { 

    4.         msg = s; 

    5.     } 

    6.     private string msg; 

    7.     public string Message 

    8.     { 

    9.         get { return msg; } 

    10.     }  

引發(fā)派生類中的基類事件

 以下簡單示例演示了在基類中聲明可從派生類引發(fā)的事件的標準方法。此模式廣泛應用于 .NET Framework 基類庫中的 Windows  窗體類。

在創(chuàng)建可用作其他類的基類的類時,必須考慮如下事實:事件是特殊類型的委托,只可以從聲明它們的類中調(diào)用。派生類無法直接調(diào)用基類中聲明的事件。盡管有時您可能希望某個事件只能通過基類引發(fā),但在大多數(shù)情形下,您應該允許派生類調(diào)用基類事件。為此,您可以在包含該事件的基類中創(chuàng)建一個受保護的調(diào)用方法。通過調(diào)用或重寫此調(diào)用方法,派生類便可以間接調(diào)用該事件。

namespace BaseClassEvents {     using System;     using System.Collections.Generic;     public class ShapeEventArgs : EventArgs     {         private double newArea;          public ShapeEventArgs(double d)         {             newArea = d;         }         public double NewArea         {             get { return newArea; }         }     }     public abstract class Shape     {         protected double area;          public double Area         {             get { return area; }             set { area = value; }         }         public event EventHandler<ShapeEventArgs> ShapeChanged;         public abstract void Draw();         protected virtual void OnShapeChanged(ShapeEventArgs e)         {             EventHandler<ShapeEventArgs> handler = ShapeChanged;             if (handler != null)             {                 handler(this, e);             }         }     }     public class Circle : Shape     {         private double radius;         public Circle(double d)         {             radius = d;             area = 3.14 * radius;         }         public void Update(double d)         {             radius = d;             area = 3.14 * radius;             OnShapeChanged(new ShapeEventArgs(area));         }         protected override void OnShapeChanged(ShapeEventArgs e)         {             base.OnShapeChanged(e);         }         public override void Draw()         {             Console.WriteLine("Drawing a circle");         }     }     public class Rectangle : Shape     {         private double length;         private double width;         public Rectangle(double length, double width)         {             this.length = length;             this.width = width;             area = length * width;         }         public void Update(double length, double width)         {             this.length = length;             this.width = width;             area = length * width;             OnShapeChanged(new ShapeEventArgs(area));         }         protected override void OnShapeChanged(ShapeEventArgs e)         {             base.OnShapeChanged(e);         }         public override void Draw()         {             Console.WriteLine("Drawing a rectangle");         }      }     public class ShapeContainer     {         List<Shape> _list;          public ShapeContainer()         {             _list = new List<Shape>();         }          public void AddShape(Shape s)         {             _list.Add(s);             s.ShapeChanged += HandleShapeChanged;         }         private void HandleShapeChanged(object sender, ShapeEventArgs e)         {             Shape s = (Shape)sender;             Console.WriteLine("Received event. Shape area is now {0}", e.NewArea);             s.Draw();         }     }     class Test     {          static void Main(string[] args)         {             Circle c1 = new Circle(54);             Rectangle r1 = new Rectangle(12, 9);             ShapeContainer sc = new ShapeContainer();             sc.AddShape(c1);             sc.AddShape(r1);             c1.Update(57);             r1.Update(7, 7);             Console.WriteLine();             Console.WriteLine("Press Enter to exit");             Console.ReadLine();         }     } }

實現(xiàn)接口事件

接口可聲明事件。下面的示例演示如何在類中實現(xiàn)接口事件。接口事件的實現(xiàn)規(guī)則與任何接口方法或?qū)傩缘膶崿F(xiàn)規(guī)則基本相同。

  • 在類中實現(xiàn)接口事件

     在類中聲明事件,然后在適當?shù)奈恢谜{(diào)用該事件。

  1. public interface IDrawingObject 

  2.     event EventHandler ShapeChanged; 

  3. public class MyEventArgs : EventArgs {&hellip;} 

  4. public class Shape : IDrawingObject 

  5.     event EventHandler ShapeChanged; 

  6.     void ChangeShape() 

  7.     { 

  8.         // Do something before the event&hellip; 

  9.         OnShapeChanged(new MyEventsArgs(&hellip;)); 

  10.         // or do something after the event.  

  11.     } 

  12.     protected virtual void OnShapeChanged(MyEventArgs e) 

  13.     { 

  14.         if(ShapeChanged != null) 

  15.         { 

  16.            ShapeChanged(this, e); 

  17.         } 

  18.     } 

  19. }

下面的示例演示如何處理以下的不常見情況:您的類是從兩個以上的接口繼承的,每個接口都含有同名事件)。在這種情況下,您至少要為其中一個事件提供顯式接口實現(xiàn)。為事件編寫顯式接口實現(xiàn)時,必須編寫  add 和 remove 事件訪問器。這兩個事件訪問器通常由編譯器提供,但在這種情況下編譯器不能提供。

您可以提供自己的訪問器,以便指定這兩個事件是由您的類中的同一事件表示,還是由不同事件表示。例如,根據(jù)接口規(guī)范,如果事件應在不同時間引發(fā),則可以將每個事件與類中的一個單獨實現(xiàn)關聯(lián)。在下面的示例中,訂戶將形狀引用強制轉(zhuǎn)換為  IShape 或 IDrawingObject,從而確定自己將會接收哪個 OnDraw 事件。

namespace WrapTwoInterfaceEvents {     using System;     public interface IDrawingObject     {         event EventHandler OnDraw;     }     public interface IShape     {         event EventHandler OnDraw;     }     public class Shape : IDrawingObject, IShape     {         event EventHandler PreDrawEvent;         event EventHandler PostDrawEvent;         event EventHandler IDrawingObject.OnDraw         {             add { PreDrawEvent += value; }             remove { PreDrawEvent -= value; }         }         event EventHandler IShape.OnDraw         {             add { PostDrawEvent += value; }             remove { PostDrawEvent -= value; }         }         public void Draw()         {             EventHandler handler = PreDrawEvent;             if (handler != null)             {                 handler(this, new EventArgs());             }             Console.WriteLine("Drawing a shape.");             handler = PostDrawEvent;             if (handler != null)             {                 handler(this, new EventArgs());             }         }     }     public class Subscriber1     {         public Subscriber1(Shape shape)         {             IDrawingObject d = (IDrawingObject)shape;             d.OnDraw += new EventHandler(d_OnDraw);         }         void d_OnDraw(object sender, EventArgs e)         {             Console.WriteLine("Sub1 receives the IDrawingObject event.");         }     }     public class Subscriber2     {         public Subscriber2(Shape shape)         {             IShape d = (IShape)shape;             d.OnDraw += new EventHandler(d_OnDraw);         }          void d_OnDraw(object sender, EventArgs e)         {             Console.WriteLine("Sub2 receives the IShape event.");         }     }     public class Program     {         static void Main(string[] args)         {             Shape shape = new Shape();             Subscriber1 sub = new Subscriber1(shape);             Subscriber2 sub2 = new Subscriber2(shape);             shape.Draw();              Console.WriteLine("Press Enter to close this window.");             Console.ReadLine();         }     } }

使用字典存儲事件實例

accessor-declarations  的一種用法是公開大量的事件但不為每個事件分配字段,而是使用字典來存儲這些事件實例。這只有在具有非常多的事件、但您預計大部分事件都不會實現(xiàn)時才有用。

  1. public delegate void EventHandler1(int i); 

  2. public delegate void EventHandler2(string s); 

  3. public class PropertyEventsSample 

  4.     private System.Collections.Generic.Dictionary<string, System.Delegate> eventTable; 

  5.     public PropertyEventsSample() 

  6.     { 

  7.         eventTable = new System.Collections.Generic.Dictionary<string, System.Delegate>(); 

  8.         eventTable.Add("Event1", null); 

  9.         eventTable.Add("Event2", null); 

  10.     } 

  11.     public event EventHandler1 Event1 

  12.     { 

  13.         add 

  14.         { 

  15.             eventTable["Event1"] = (EventHandler1)eventTable["Event1"] + value; 

  16.         } 

  17.         remove 

  18.         { 

  19.             eventTable["Event1"] = (EventHandler1)eventTable["Event1"] - value; 

  20.         } 

  21.     } 

  22.     public event EventHandler2 Event2 

  23.     { 

  24.         add 

  25.         { 

  26.             eventTable["Event2"] = (EventHandler2)eventTable["Event2"] + value; 

  27.         } 

  28.         remove 

  29.         { 

  30.             eventTable["Event2"] = (EventHandler2)eventTable["Event2"] - value; 

  31.         } 

  32.     } 

  33.     internal void RaiseEvent1(int i) 

  34.     { 

  35.         EventHandler1 handler1; 

  36.         if (null != (handler1 = (EventHandler1)eventTable["Event1"])) 

  37.         { 

  38.             handler1(i); 

  39.         } 

  40.     } 

  41.     internal void RaiseEvent2(string s) 

  42.     { 

  43.         EventHandler2 handler2; 

  44.         if (null != (handler2 = (EventHandler2)eventTable["Event2"])) 

  45.         { 

  46.             handler2(s); 

  47.         } 

  48.     } 

  49. public class TestClass 

  50.     public static void Delegate1Method(int i) 

  51.     { 

  52.         System.Console.WriteLine(i); 

  53.     } 

  54.     public static void Delegate2Method(string s) 

  55.     { 

  56.         System.Console.WriteLine(s); 

  57.     } 

  58.     static void Main() 

  59.     { 

  60.         PropertyEventsSample p = new PropertyEventsSample(); 

  61.  

  62.         p.Event1 += new EventHandler1(TestClass.Delegate1Method); 

  63.         p.Event1 += new EventHandler1(TestClass.Delegate1Method); 

  64.         p.Event1 -= new EventHandler1(TestClass.Delegate1Method); 

  65.         p.RaiseEvent1(2); 

  66.  

  67.         p.Event2 += new EventHandler2(TestClass.Delegate2Method); 

  68.         p.Event2 += new EventHandler2(TestClass.Delegate2Method); 

  69.         p.Event2 -= new EventHandler2(TestClass.Delegate2Method); 

  70.         p.RaiseEvent2("TestString"); 

  71.     } 

  72. }

事件的異步模式

有多種方式可向客戶端代碼公開異步功能。基于事件的異步模式為類規(guī)定了用于顯示異步行為的建議方式。對于相對簡單的多線程應用程序,BackgroundWorker  組件提供了一個簡單的解決方案。對于更復雜的異步應用程序,請考慮實現(xiàn)一個符合基于事件的異步模式的類。

  • “在后臺”執(zhí)行耗時任務(例如下載和數(shù)據(jù)庫操作),但不會中斷您的應用程序。

  • 同時執(zhí)行多個操作,每個操作完成時都會接到通知。

  • 等待資源變得可用,但不會停止(“掛起”)您的應用程序。

  • 使用熟悉的事件和委托模型與掛起的異步操作通信。

看完上述內(nèi)容,你們對如何理解.Net事件有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

分享文章:如何理解.Net事件
路徑分享:http://www.chinadenli.net/article18/piisgp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化網(wǎng)站設計公司靜態(tài)網(wǎng)站網(wǎng)站內(nèi)鏈標簽優(yōu)化品牌網(wǎng)站建設

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)