第七章 事件及事件驱动

本文深入探讨了.NET框架中事件处理机制的核心概念,包括事件与委托的关系、事件的实现机制,以及如何处理委托链表中的异常。通过实例,详细解释了事件如何在对象间传递消息,以及事件处理程序的注册和注销过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 .NET 事件处理机制的剖析与应用

1.1 直观理解 “事件” 的概念

1.2 事件与委托的关系

1.3 .NET 事件实现机制剖析

1.4 委托链表的分步调用


1 .NET 事件处理机制的剖析与应用

1.1 直观理解 “事件” 的概念

事件建立于委托的基础之上。

从面向对象角度来说,事件是由对象发出的消息,它是一个信号,通知其它对象有事情发生。例如,用户单击窗体上的某个控件时,控件可能会激发一个 Click 事件。

激发与响应事件的载体都是对象。激发事件的对象被称为 “事件源”,对这个事件进行响应的对象称为 “响应者”,响应者必须提供一个 “事件响应(或处理)方法”

1.2 事件与委托的关系

事件的激发必须由事件源对象自己引发,不应该允许由外界引发。为了限制事件的激发只能由事件源对象自己引发,C# 引入了一个新的关键字 —— event。

在定义委托成员的时候给出 event 关键字进行修饰,前面加了 event 关键字修饰的 public 委托成员,只能在类外部进行附加和移除操作,而调用操作只能发生在类的内部。

public partial class Form1 : Form
{
   Form2 m_objForm2 = new Form2();
   public Form1()
   {
       InitializeComponent();
       m_objForm2.Show();
       m_objForm2.eventClick += OnCount; // 使用事件方式实现回调
       // m_objForm2.eventClick(10);  // Error:不允许外界直接触发事件
   }

   private void OnCount(int nCount)
   {
       m_txt_Count.Text = nCount.ToString();
   }

   private void m_hsb_Num_Scroll(object sender, ScrollEventArgs e)
   {
       m_objForm2.OnChange(m_hsb_Num.Value);
   }
}

public partial class Form2 : Form
{
   public Form2()
   {
       InitializeComponent();
   }

   public event Action<int> eventClick;
   private int nCount = 0;

   private void m_btn_Event_Click(object sender, EventArgs e)
   {
       nCount++;
       if (eventClick != null) // 在激发事件前,判断事件是否为空
       {
           eventClick(nCount); // 激发事件
       }
   }

   public void OnChange(int nNum)
   {
       m_pBar_Num.Value = nNum;
   }
}

调用加了 event 关键字修饰的委托也称为 “激发事件”,调用方称为 “事件发布者”,被调用方称为 “事件注册者”,附加委托的过程称之为 “注册事件”,移除委托的过程称之为 “注销事件”。通过委托调用的方法称为 “事件处理程序”。

1.3 .NET 事件实现机制剖析

使用Visual Studio 创建一个 Windows Forms 应用程序,往窗体上拖一个按钮控件 button1,双击按钮,将会在 Form1.cs 文件中生成一个事件响应方法框架:

private void button1_Click(object sender, EventArgs e)

{ ... }

注意这一方法有两个参数,第一个参数 sender 代表了事件源对象,第二个参数 e 代表与事件相关的信息。

相应的,“Form1.Designer.cs” 文件中会增加一行:

this.button1.Click += new System.EventHandler(this.button1_Click);

上述代码中的 “Click” 是按钮基类 Control 的成员,它被定义为一个事件:

public event EventHandler Click;

Click 事件定义中所用到 “EventHandler” 是 .NET Framework 基类库所提供的一个预定义委托,其声明如下:

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

1.4 委托链表的分步调用

当我们调用委托链时,如果某一个委托对应的方法抛出了异常,那么剩下的其它委托将不再调用。为了解决这个问题,我们需要分步调用每个委托,将每一步的调用代码均放在 try/catch 块中。

public void DoSomething()
{
   Action tmp = SomeEvent;
   if (tmp != null)
   {
       Delegate[] delegates = tmp.GetInvocationList();
       foreach (Delegate d in delegates)
       {
           Action del = d as Action;
           try
           {
               del();
           }
           catch (System.Exception ex)
           {   

           }
       }
   }
}

上述代码中,我们没有直接使用 tmp 来调用委托链表,而是先通过 tmp.GetInvocationList 方法来获取委托链表中的委托集合,然后再使用 foreach 循环遍历集合,分布调用每个委托,分步调用过程均放在了 try/catch 块中,这样一来,任何一个方法抛出异常都不会影响到其它委托的调用。

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值