vb.net 中自定义类中的事件
'1.先定义包含事件的类(如下) Public Class TestEvent '2.在使用事件的类中添加如下代码 3.
vb.net 中自定义类中的事件
Private name As String Public Event walked(ByVal distance As Integer)
Dim i As Int16 '''定义一个变量
从窗体: Public WithEvents main As main '''定义主窗体事件并执行
1,以上方法是主窗体定义事件,然后触发,在从窗体执行的情况,需要注意的是frm.main=me 此句的意思是从窗体的触发事件是主窗体定义的 2,但是在现实应用中,通常都是从窗体内容发生变化,需要及时更新主窗体,此时代码有小小的变动,如下, 需要仔细看啊! 主窗体:
从窗体:
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/longge7685/archive/2009/06/09/4253203.aspx another blog 首先来看一下我们常见的自定义事件实现方式,首先创建可能的事件参数 DemoEventArgs:EventArgs { 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上,我们可以查阅到最后由一个注意事项:“实例或类型上的锁定(如同使用 Synchronized 标志一样)对于公共类型是不推荐使用的,其原因在于除了不是自己的代码的其他代码可对公共类型和实例采用锁定。这可能导致死锁或其他同步问题。 ” 线程同步的指导方针是不应该在对象本身上加同步锁,因为同步锁将对所有的代码公开,这意味着任何人都有可能蓄意的编写代码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} 从性能上考虑,当某个组件定义大量事件时,该实例会浪费大量的内存,之所以是浪费,是因为其中很多事件都没有被订阅。这一点,我们可以参考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来存储委托链。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |