吵吵   2014-06-21  阅读:1,814

c#的serialPort控件有个DataReceived事件,用来响应串口接收到发送来的数据。在做LIS接口的时候,本着”高内聚、低耦合“的原则,我继承了这个控件,并且重新定义了两个事件ResultReceived和QueryReceived,用来响应LIS接口收到结果和收到条码请求两个事件。为了实现上述的功能,就需要了解自定义事件怎么做?

为了了解这个问题,我们追踪一下源代码,发现DataReceived事件代码如下:

public event SerialDataReceivedEventHandler DataReceived;

这其实是一个叫SerialDataReceivedEventHandler的事件,而继续追踪之则有:

public delegate void SerialDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e);

原来定义的这个玩意儿是个委托。看到这里,似乎有恍然大悟的感觉,但是我们觉得有必要再深究一下:

1、为什么要用委托?

为什么要用委托,其实一开始就说明了,委托可以实现各个模块的”高内聚、低耦合“。在异步编程中,如果你想要让各个模块结合的更加松散一点,就必须要用到委托。

这么说好像是很抽象,打个比方可能就很好理解。假设A,B两个人代表两个模块或者说两个类。A想和B一起去吃饭,但是不知道B什么时候会去吃饭。按照顺序逻辑来编程,要实现这个功能,那么逻辑是:A去B那里,A等待,B去吃饭,A和B一起去吃饭。整个过程就是A在那里一直傻傻的盯着B。因此你会说,这太他妈的傻了,浪费时间和精力啊。解决办法是什么呢?就是B去吃饭的时候,告诉A一下,而这个告诉正是定义的委托。

2、委托和回调函数有什么不同。

看到这里,你会说,瞎扯啥委托啊,搞的这么高深,在C里面这个玩意儿就是回调函数CallBack,例如SetTimer API就可以通过一个callback的函数来调用到时间要执行的程序。

真的是这么简单么,那为什么不直接搞回调函数算了?c#当然有它的高明之处:

1)函数指针只能指向静态函数,是要加static标志的,是只能调用全局函数的。而delegate既可以引用静态函数,又可以引用非静态成员函数。还记得当年我们写callback函数时候只能写成全局函数,因此无法引用类中的变量和方法有多纠结么?如果你不记得可以看看吵吵这篇文章

vc中SetTimer回调类的成员函数

当初为了将类的实例传递到回调函数中,要么用全局变量,要么你作为参数传递进去!

那是多么痛的过去啊,c#的委托比回调函数强大多了,因为在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。

2)与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。

总而言之,委托比回调,是方便好用,又安全可靠。

3、event这个玩意儿有用么?

讲到这里,你会发现,事件不就是个委托么?那么在写代码的时候,不加event关键词可不可以呢?比如上述的DataReceived去掉event:

public SerialDataReceivedEventHandler DataReceived;

你会发现这样子是可行的,完全木有啥问题,那么加了有啥用呢,加了之后你发现不能serialport.dataReceived=XX,而只能是serialport.dataReceived+=XX了!

换言之,event是更加安全一点的delegate了。

最后,看看怎么自定义事件吧!

1、定义一个委托:

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

2、在该类中,增加相应的事件

public event ReceiveResultEventHandler ReceiveResult;

3、在激活事件的地方写入代码:

ReceiveResult(this, new EventArgs());

至于事件中的两个参数,我就不再讲了,你可以研究研究!

今天到次为止,明天开始写CS5100的LIS接口协议!

吵吵微信朋友圈,请付款实名加入:

吵吵 吵吵

3条回应:“c#自定义事件”

  1. 笔砚且勿弃,苏张曾陆沉。

  2. 莫小诺说道:

    网赚客www.67px.com

  3. 莫小诺说道:

    在家上网赚钱的方法www.67px.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注