日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.Net 事件类型的实现和推荐做法

發布時間:2024/4/11 asp.net 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .Net 事件类型的实现和推荐做法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先來看一下我們常見的自定義事件實現方式,首先創建可能的事件參數

?1?///?<summary>
?2?????///?事件參數
?3?????///?</summary>
?4?????public?sealed?class?DemoEventArgs:EventArgs?{
?5?
?6?????????///?<summary>
?7?????????///?獲取或設置事件的上下文
?8?????????///?</summary>
?9?????????public?string?Context?{
10?????????????get?{?return?context;?}
11?????????????set?{?context?=?value;?}
12?????????}
13?????????private?string?context;
14?
15?
16?????} 當然,如果在實際使用中不需要事件參數的話,可以直接使用EventArgs.Empty靜態字段。
緊接著我們需要定義事件成員
1/**////?<summary>
2????????///?事件成員
3????????///?</summary>

4????????public?event?EventHandler<DemoEventArgs>?NewEv 然后,我們就需要引發這個事件
?1?public?void?InvokeNewEvent()?{
?2?????????????DemoEventArgs?e?=?new?DemoEventArgs();
?3?????????????e.Context?=?"Hello?world";
?4?????????????this.OnNewEvent(e);
?5?????????}
?6?
?7?????????protected?virtual?void?OnNewEvent(DemoEventArgs?e)?{
?8?????????????if?(NewEvent!=null)?{
?9?????????????????NewEvent(this,?e);
10?????????????}
11?????????}
對于上面的代碼,我們通過Reflector工具可以看到,對于事件定義
public?event?EventHandler<DemoEventArgs>?NewEvent;

編譯程序會將其翻譯成兩個public方法。

相應代碼如下
?1[MethodImpl(MethodImplOptions.Synchronized)]
?2public?void?add_NewEvent(EventHandler<DemoEventArgs>?value)
?3{
?4????this.NewEvent?=?(EventHandler<DemoEventArgs>)?Delegate.Combine(this.NewEvent,?value);
?5}

?6
?7[MethodImpl(MethodImplOptions.Synchronized)]
?8public?void?remove_NewEvent(EventHandler<DemoEventArgs>?value)
?9{
10????this.NewEvent?=?(EventHandler<DemoEventArgs>)?Delegate.Remove(this.NewEvent,?value);
11}

12
13?
14
15?
16

MethodImpOption枚舉類型定義了方法是如何被執行的。Synchronized指定了同時只能由一個線程執行該方法。靜態方法鎖定類型,而實例方法鎖定實例。這樣做的目的是,保證在操作實例事件時,對于每一個對象,在同一時刻add和remove方法的線程安全。
在類型上,所有事件的add和remove方法都將使用相同的鎖。這樣造成,在多個線程同時對不同事件進行訂閱和撤銷的時候,就會出現性能損失。在MSDN上,我們可以查閱到最后由一個注意事項:“實例或類型上的鎖定(如同使用 標志一樣)對于公共類型是不推薦使用的,其原因在于除了不是自己的代碼的其他代碼可對公共類型和實例采用鎖定。這可能導致死鎖或其他同步問題。 ”
線程同步的指導方針是不應該在對象本身上加同步鎖,因為同步鎖將對所有的代碼公開,這意味著任何人都有可能蓄意的編寫代碼Lock這個對象,造成其它線程死鎖。

為此,在大多數情況下上述情況并不可能發生,但是對于一個完美而穩固的組件來說,這就顯得相當重要。鑒于以上原因,我們重新定義事件的實現。

?1?public?class?EventDemo?{
?2????????/**////?<summary>
?3????????///?私有同步鎖
?4????????///?</summary>

?5????????private?readonly?object?_eventLock?=?new?object();?
?6
?7????????/**////?<summary>
?8????????///?事件成員
?9????????///?</summary>

10????????private?event?EventHandler<DemoEventArgs>?internalNewEvent;
11????????public?event?EventHandler<DemoEventArgs>?NewEvent?{
12????????????add?{
13????????????????lock?(_eventLock)?{
14????????????????????internalNewEvent?+=?value;
15????????????????}

16????????????}

17????????????remove?{
18????????????????lock?(_eventLock)?{
19????????????????????internalNewEvent?-=?value;
20????????????????}

21????????????}

22????????}

23
24????????protected?virtual?void?OnNewEvent(DemoEventArgs?e)?{
25????????????//出于線程考慮,委托字段保存到臨時字段中
26????????????EventHandler<DemoEventArgs>?t?=?internalNewEvent;
27????????????if?(t!=null)?{
28????????????????internalNewEvent(this,?e);
29????????????}

30????????}

31
32????????public?void?InvokeNewEvent()?{
33????????????DemoEventArgs?e?=?new?DemoEventArgs();
34????????????e.Context?=?"Hello?world";
35????????????this.OnNewEvent(e);
36????????}

37
38????????
39
40????}

再次查看編譯程序最終生成的運行時代碼

?1public?void?add_NewEvent(EventHandler<DemoEventArgs>?value)
?2{
?3????lock?(this._eventLock)
?4????{
?5????????this.internalNewEvent?=?(EventHandler<DemoEventArgs>)?Delegate.Combine(this.internalNewEvent,?value);
?6????}

?7}

?8
?9public?void?remove_NewEvent(EventHandler<DemoEventArgs>?value)
10{
11????lock?(this._eventLock)
12????{
13????????this.internalNewEvent?=?(EventHandler<DemoEventArgs>)?Delegate.Remove(this.internalNewEvent,?value);
14????}

15}

16
17?
18
19?
20

從性能上考慮,當某個組件定義大量事件時,該實例會浪費大量的內存,之所以是浪費,是因為其中很多事件都沒有被訂閱。這一點,我們可以參考System.Web.UI.Control中的實現。首先在內部包含了一個EventHandlerList類型的Events屬性。

?protected?EventHandlerList?Events
????
{
????????
get
????????
{
????????????
this.EnsureOccasionalFields();
????????????
if?(this._occasionalFields.Events?==?null)
????????????
{
????????????????
this._occasionalFields.Events?=?new?EventHandlerList();
????????????}

????????????
return?this._occasionalFields.Events;
????????}

????}

?

?public?event?EventHandler?DataBinding
????
{
????????add
????????
{
????????????
this.Events.AddHandler(EventDataBinding,?value);
????????}

????????remove
????????
{
????????????
this.Events.RemoveHandler(EventDataBinding,?value);
????????}

????}

引發事件

?protected?virtual?void?OnDataBinding(EventArgs?e)
????
{
????????
if?(this.HasEvents())
????????
{
????????????EventHandler?handler?
=?this._occasionalFields.Events[EventDataBinding]?as?EventHandler;
????????????
if?(handler?!=?null)
????????????
{
????????????????handler(
this,?e);
????????????}

????????}

????}

這樣實現自我感覺不是很好,由于EventHandlerList是一個鏈表,造成通過內部的find方法查找時,要遍歷循環。更理想的做法是使用一個Hashtable來存儲委托鏈。
(參考:CLR via C#)
?

轉載于:https://www.cnblogs.com/DreamWinter/archive/2007/08/15/856666.html

總結

以上是生活随笔為你收集整理的.Net 事件类型的实现和推荐做法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。