原文:http://www.cnblogs.com/michaelxu/archive/2008/04/02/1134217.html

事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂。而这些东西却往往又是编程中常用且非常重要的东西。大家都知道windows消息处理机制的重要,其实C#事件就是基于windows消息处理机制的,只是封装的更好,让开发者无须知道底层的消息处理机制,就可以开发出强大的基于事件的应用程序来。

先来看看事件编程有哪些好处。
在以往我们编写这类程序中,往往采用等待机制,为了等待某件事情的发生,需要不断地检测某些判断变量,而引入事件编程后,大大简化了这种过程:
- 使用事件,可以很方便地确定程序执行顺序。
- 当事件驱动程序等待事件时,它不占用很多资源。事件驱动程序与过程式程序最大的不同就在于,程序不再不停地检查输入设备,而是呆着不动,等待消息的到来,每个输入的消息会被排进队列,等待程序处理它。如果没有消息在等待,则程序会把控制交回给操作系统,以运行其他程序。
- 事件简化了编程。操作系统只是简单地将消息传送给对象,由对象的事件驱动程序确定事件的处理方法。操作系统不必知道程序的内部工作机制,只是需要知道如何与对象进行对话,也就是如何传递消息。

  有了这么多好处,看来我们的确有必要掌握它。俗话说:“难了不会,会了不难”。就让我们一步一步开始吧...

  要讲事件,必然要讲到委托(delegate)。它们之间的关系可以通过一个浅显的比方来说明,这个比方可能不是十分恰当。比如你要租一个房屋,这是一个事件,那么委托就是房屋租赁中介,当你把租房子的消息告知中介后,中介就会产生出一套符合你要求的房屋租赁方案来。再由中介执行这套方案,你便租得了这个房屋,即事件被处理了。当然你也可以不通过中介,直接找房东,但如果没有互联网等工具,你如何得到谁出租房屋的信息?话题扯远了。

委托(delegate)
委托可以理解成为函数指针,不同的是委托是面向对象,而且是类型安全的。关于委托的理解,可以参考我的另一篇文章《C#委托之个人理解》。

事件(event)
  我们可以把事件编程简单地分成两个部分:事件发生的类(书面上叫事件发生器)和事件接收处理的类。事件发生的类就是说在这个类中触发了一个事件,但这个类并不知道哪个个对象或方法将会加收到并处理它触发的事件。所需要的是在发送方和接收方之间存在一个媒介。这个媒介在.NET Framework中就是委托(delegate)。在事件接收处理的类中,我们需要有一个处理事件的方法。好了,我们就按照这个顺序来实现一个捕获键盘按键的程序,来一步一步说明如何编写事件应用程序。

1、首先创建一个自己的EventArgs类。
引自MSDN:
EventArgs是包含事件数据的类的基类,此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。

因为在我们键盘按键事件中要包含按键信息,所以要派生一个KeyEventArgs类,来保存按键信息,好让后面知道按了哪个键。

internalclassKeyEventArgs : EventArgs
{
    private char keyChar;
    public KeyEventArgs( char keyChar ) : base()
    {
        this.keyChar = keyChar;
    }

    public char KeyChar
    {
        get
        {
            return keyChar;
        }
    }
}

2、再创建一个事件发生的类KeyInputMonitor,这个类用于监控键盘按键的输入并触发一个事件:

internalclassKeyInputMonitor
{
    // 创建一个委托,返回类型为void,两个参数
    public delegate void KeyDown( object sender, KeyEventArgs e );
    // 将创建的委托和特定事件关联,在这里特定的事件为OnKeyDown
    public event KeyDown OnKeyDown;

    public void Run()
    {
        bool finished = false;
        do
        {
            Console.WriteLine( "Input a char" );
            string response = Console.ReadLine();

            char responseChar = ( response == "" ) ? ' ' : char.ToUpper( response[0] );
            switch( responseChar )
            {
                case 'X':
                    finished = true;
                    break;
                default:
                    // 得到按键信息的参数
                    KeyEventArgs keyEventArgs = new KeyEventArgs( responseChar );
                    // 触发事件
                    OnKeyDown( this, keyEventArgs );
                    break;
            }
        }while( !finished );
    }
}

这里注意OnKeyDown( this, KeyEventArgs );一句,这就是触发事件的语句,并将事件交由KeyDown这个委托来处理,委托指定事件处理方法去处理事件,这就是事件接收方的类的事情了。参数this是指触发事件的对象就是本身这个对象,keyEventArgs包含了按键信息。

3、最后创建一个事件接收方的类,这个类先产生一个委托实例,再把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件。然后提供一个方法回显按键信息。

internalclassEventReceiver
{
    public EventReceiver( KeyInputMonitor monitor )
    {
        // 产生一个委托实例并添加到KeyInputMonitor产生的事件列表中
        monitor.OnKeyDown += new KeyInputMonitor.KeyDown( this.Echo );
    }
    private void Echo(object sender, KeyEventArgs e)
    {
        // 真正的事件处理函数
        Console.WriteLine( "Capture key: {0}", e.KeyChar );
    }
}

4、看一下如何调用

publicclassMainEntryPoint
{
    public static void Start()
    {
        // 实例化一个事件发送器
        KeyInputMonitor monitor = new KeyInputMonitor();
        // 实例化一个事件接收器
        EventReceiver eventReceiver = new EventReceiver( monitor );
        // 运行
        monitor.Run();
    }
}

总结:

C#中使用事件需要的步骤:
1.创建一个委托
2.将创建的委托与特定事件关联(.Net类库中的很多事件都是已经定制好的,所以他们也就有相应的一个委托,在编写关联事件处理程序--也就是当有事件发生时我们要执行的方法的时候我们需要和这个委托有相同的签名)
3.编写事件处理程序
4.利用编写的事件处理程序生成一个委托实例
5.把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件

C#中事件产生和实现的流程:
1.定义A为产生事件的实例,a为A产生的一个事件
2.定义B为接收事件的实例,b为处理事件的方法
3.A由于用户(程序编写者或程序使用者)或者系统产生一个a事件(例如点击一个Button,产生一个Click事件)
4.A通过事件列表中的委托对象将这个事件通知给B
5.B接到一个事件通知(实际是B.b利用委托来实现事件的接收)
6.调用B.b方法完成事件处理
    public class A
    {
        public delegate void EventHandler(object sender);
        public event EventHandler a;

public void Run()
        {
            Console.WriteLine("Trigger an event.");
            a(this);
        }
    }

class B
    {
        public B(A a)
        {
            a.a += new A.EventHandler(this.b);
        }
        private void b(object sender)
        {
            Console.WriteLine("Received and handled an event." );
            Console.Read();
        }
    }
不当之处,欢迎指正。
(完)

本文转自麒麟博客园博客,原文链接:http://www.cnblogs.com/zhuqil/archive/2009/12/30/1636082.html,如需转载请自行联系原作者

C#事件(event)解析相关推荐

  1. C#事件(event)解析(转)

    事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道 windows消息处理机制的重要,其实C#事件就是基于windo ...

  2. 事件EVENT,WaitForSingleObject(),WaitForMultipleObjecct()和SignalObjectAndWait() 的使用(上)

    用户模式的线程同步机制效率高,如果需要考虑线程同步问题,应该首先考虑用户模式的线程同步方法.但是,用户模式的线程同步有限制,对于多个进程之间的线程同步,用户模式的线程同步方法无能为力.这时,只能考虑使 ...

  3. solidity采坑日记之智能合约返回事件内容解析

    最近在用java调用solidity智能合约方法的时候,遇到了方法Log解析的问题. 正常在调用合约后,如果该合约有event时间,那么执行结果会返回对应的log日志,但是返回的log日志是0x开头的 ...

  4. Spring 注解事件Event

    2019独角兽企业重金招聘Python工程师标准>>> String event 从Spring的4.2版本后,开始支持注解来进行事件广播接收,这使得我们非常方便 当然了Spring ...

  5. iOS事件全面解析 (触摸事件、手势识别、摇晃事件、耳机线控)

    -- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...

  6. python 同步 事件 event 简介

    目录 1. Event 1.1 set() 1.2 wait() 1.3 clear() 1.4 is_set() 2. 协调线程同步 3. 一个更复杂的例子 事件 Event是另一种python多线 ...

  7. 秒杀多线程第六篇 经典线程同步 事件Event

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...

  8. [数据库] Navicat for MySQL事件Event实现数据每日定期操作

    在我们操作数据库过程中,通常会遇到一些某个时间点操作数据库的问题,例如:         (1).每天凌晨12点对数据库进行定时备份,结算和汇总:         (2).每天凌晨2点删除数据库前三天 ...

  9. C#总结(二)事件Event 介绍总结

    最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...

最新文章

  1. homebrew的安装和使用
  2. PostgreSQL Oracle 兼容性之 - PL/SQL DETERMINISTIC 与PG函数稳定性(immutable, stable, volatile)...
  3. svn: Checksum mismatch while updating 'D:\workspace\demo\test\.svn\text-base\test.php.svn-base'
  4. Activity的launchMode和任务栈小结
  5. 字符串的展开(洛谷-P1098)
  6. 华为杨超斌:5G千元机有望明年底上市
  7. 程序员如何保护好自己的发际线
  8. linux zen 补丁,Mageia 7.1 发布,修复AMD Zen 2支持
  9. 制作纯DOS启动U盘
  10. 对角化求可逆矩阵_矩阵对角化方法
  11. 题529. 扫雷游戏
  12. linux v4l2-ctl,V4L2总结
  13. 【图像分类】华为云·垃圾分类亚军方案分享
  14. 用Python破解摩斯密码
  15. 几种基本的约束和外键(一对一 多对多 多对一)级联关系
  16. ALTER ROUTINE 语句
  17. 工具BlueSoleil千月蓝牙破解版,最好的蓝牙驱动
  18. 如何在EDUIS中导出ETL字幕模板_教大家Edius如何设置导出mp4格式视频
  19. 用热塑技术修复供水(给水)燃气等压力管道的非开挖技术
  20. php 过滤粘贴_粘贴过滤的数据时出现错误1004

热门文章

  1. 8)排序①排序算法之交换排序[1]冒泡排序法
  2. 守住你的网站:防御DDoS***指南
  3. 免费资源:Typicons-免费图标字体
  4. SQL临时表的生存期问题
  5. Docker了解(官方解读)
  6. Android国际化(多语言)实现,支持8.0
  7. Handler.removeMessages的作用,有时候为什么一定要先remove一下呢
  8. ubuntu 12.04 clang 3.4 安装
  9. Windows 2003 系统应用故障的分析
  10. 分享.NET 3.5的书籍下载(2009-04-01更新Silverlight 2书籍打包)