C# 事件 event 【转】
C#事件(event)解析
事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂。而这些东西却往往又是编程中常用且非常重要的东西。大家都知道windows消息处理机制的重要,其实C#事件就是基于windows消息处理机制的,只是封装的更好,让开发者无须知道底层的消息处理机制,就可以开发出强大的基于事件的应用程序来。
先来看看事件编程有哪些好处。
在以往我们编写这类程序中,往往采用等待机制,为了等待某件事情的发生,需要不断地检测某些判断变量,而引入事件编程后,大大简化了这种过程:
- 使用事件,可以很方便地确定程序执行顺序。
- 当事件驱动程序等待事件时,它不占用很多资源。事件驱动程序与过程式程序最大的不同就在于,程序不再不停地检查输入设备,而是呆着不动,等待消息的到来,每个输入的消息会被排进队列,等待程序处理它。如果没有消息在等待,则程序会把控制交回给操作系统,以运行其他程序。
- 事件简化了编程。操作系统只是简单地将消息传送给对象,由对象的事件驱动程序确定事件的处理方法。操作系统不必知道程序的内部工作机制,只是需要知道如何与对象进行对话,也就是如何传递消息。
有了这么多好处,看来我们的确有必要掌握它。俗话说:“难了不会,会了不难”。就让我们一步一步开始吧...
要讲事件,必然要讲到委托(delegate)。它们之间的关系可以通过一个浅显的比方来说明,这个比方可能不是十分恰当。比如你要租一个房屋,这是一个事件,那么委托就是房屋租赁中介,当你把租房子的消息告知中介后,中介就会产生出一套符合你要求的房屋租赁方案来。再由中介执行这套方案,你便租得了这个房屋,即事件被处理了。当然你也可以不通过中介,直接找房东,但如果没有互联网等工具,你如何得到谁出租房屋的信息?话题扯远了。
委托(delegate)
委托可以理解成为函数指针,不同的是委托是面向对象,而且是类型安全的。关于委托的理解,可以参考我的另一篇文章《C#委托之个人理解》。
事件(event)
我们可以把事件编程简单地分成两个部分:事件发生的类(书面上叫事件发生器)和事件接收处理的类。事件发生的类就是说在这个类中触发了一个事件,但这个类并不知道哪个个对象或方法将会加收到并处理它触发的事件。所需要的是在发送方和接收方之间存在一个媒介。这个媒介在.NET Framework中就是委托(delegate)。在事件接收处理的类中,我们需要有一个处理事件的方法。好了,我们就按照这个顺序来实现一个捕获键盘按键的程序,来一步一步说明如何编写事件应用程序。
1、首先创建一个自己的EventArgs类。
引自MSDN:
EventArgs是包含事件数据的类的基类,此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。
因为在我们键盘按键事件中要包含按键信息,所以要派生一个KeyEventArgs类,来保存按键信息,好让后面知道按了哪个键。
{
private char keyChar;
public KeyEventArgs( char keyChar ) : base()
{
this.keyChar = keyChar;
}
public char KeyChar
{
get
{
return keyChar;
}
}
}
2、再创建一个事件发生的类KeyInputMonitor,这个类用于监控键盘按键的输入并触发一个事件:
{
// 创建一个委托,返回类型为void,两个参数
public delegate void KeyDownHandler( object sender, KeyEventArgs e );
// 将创建的委托和特定事件关联,在这里特定的事件为KeyDown
public event KeyDownHandler KeyDown;
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 );
// 触发事件
KeyDown( this, keyEventArgs );
break;
}
}while( !finished );
}
}
这里注意KeyDown( this, KeyEventArgs );一句,这就是触发事件的语句,并将事件交由KeyDownHandler这个委托来处理,委托指定事件处理方法去处理事件,这就是事件接收方的类的事情了。参数this是指触发事件的对象就是本身这个对象,keyEventArgs包含了按键信息。
3、最后创建一个事件接收方的类,这个类先产生一个委托实例,再把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件。然后提供一个方法回显按键信息。
{
public EventReceiver( KeyInputMonitor monitor )
{
// 产生一个委托实例并添加到KeyInputMonitor产生的事件列表中
monitor.KeyDown += new KeyInputMonitor.KeyDownHandler( this.OnKeyDown );
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
// 真正的事件处理函数
Console.WriteLine( "Capture key: {0}", e.KeyChar );
}
}
4、看一下如何调用
{
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/michaelxu/archive/2008/04/02/1134217.html
C# 事件 event 【转】的更多相关文章
- 事件EVENT与waitforsingleobject的使用
事件event与waitforsingleobject的配合使用,能够解决很多同步问题,也可以在数据达到某个状态时启动另一个线程的执行,如报警. event的几个函数: 1.CreateEvent和O ...
- 经典线程同步 事件Event
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...
- C#事件(event)解析
事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要,其实C#事件就是基于window ...
- 【温故知新】c#事件event
从上一篇文章[温故知新]C#委托delegate可知,委托delegate和事件Event非常的相似,区别就是event关键字,给delegate穿上了个“马甲”. 让我们来看官方定义: 类或对象可以 ...
- 事件[event]_C#
事件(event): 1. 事件是类在发生其关注的事情时用来提供通知的方式.例如,封装用户界面控件的类可以定义一个在单击该控件时发生的事件.控件类不关心单击按钮时发生了什么,但它需要告知派 ...
- C#中的委托(Delegate)和事件(Event)
原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...
- MFC线程(三):线程同步事件(event)与互斥(mutex)
前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFu ...
- 重温委托(delegate)和事件(event)
1.delegate是什么 某种意义上来讲,你可以把delegate理解成C语言中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作 ...
- C#总结(二)事件Event 介绍总结
最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...
- 多线程面试题系列(6):经典线程同步 事件Event
上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题.首先 ...
随机推荐
- 如何开启GZIP
服务器设置 gzip 压缩是 web 开发里很普遍的做法.假设你要请求一个 100k 的文件,网络传输速度为 50k/s,需要 2s 才能得到数据,但是如果在服务器设置了 gzip 压缩,将服务端的文 ...
- tomcat catalina.out切割脚本
shell脚本catalina.out 切割脚本...每天23.30切割.删除七天之前的日志这里3个tomcat实例(1)拷贝日志文件(2)清空日志文件*只能清空如果删除tomcat不重启不会生成新的 ...
- 【转】实战USB接口手机充电 看3.0/2.0谁更快
原文网址:http://mb.it168.com/a2012/0816/1385/000001385641_all.shtml [IT168 应用]当下,越来越多的电脑都已普及USB 3.0接口,新买 ...
- Oracle 10g RAC OCR 和 VotingDisk 的备份与恢复
Oracle RAC 中OCR 和Voting Disk 备份在我的blog: Oracle RAC 常用维护工具和命令 中已经有说明,现在再次把它单独拿出做一个说明, 因为OCR 和Voting D ...
- tomcat下安装jenkins
参考网址:http://www.cnblogs.com/edward2013/p/5269465.html 5.安装Jenkins 方法1: jenkins.war下载地址: http://mir ...
- C# OracleBulkCopy 批量插入oracle数据库的方法
只有安装了oracle 11G客户端的机器上才可以用,要用到ODP.NET组件中的oracleDataAccess.DLL,命名空间引用为Oracle.DataAccess.Client; 引用:Or ...
- 关于seo优化的核心思想
简单说下,针对网页检索结果进行评估,主要是围绕精确率和召回率进行,具体如下:1.相关性:query与结果说的是不是一回事2.需求强度:抓住主要需求3.丰富程度:详细全面4.有效性:能否真正满足5.时效 ...
- vue 之radio绑定v-model
示例: 单选radio <label ><input type="radio" value="0" v-model="branch& ...
- shell打印彩色输出
字体颜色(8种,3开头) 重置=0,黑色=30,红色=31,绿色=32, 黄色=33,蓝色=34, 洋红=35, 青色=36, 白色=37. 背景颜色(8种,4开头) 重置=0,黑色=40,红色=41 ...
- 神奇的null和undefined
在JavaScript中,有两个特殊的类型存在,它们都只有一个值,分别null和undefined,之所以将它们放在一块,是因为在使用方面它们有很多相似之处. 相同点 在JavaScript中,nul ...