CLI中,事件是一种当某种重要事情发生时,为客户程序提供通知的机制。鼠标单击就是事件的一个典型例子,在事件发生之前,有关的客户程序必须先注册它们感兴趣的事件,如,当检测到鼠标单击时,这些程序就会接到通知。
通过添加或删除一个或多个感兴趣的事件,事件列表可在运行时增长或缩减,请看例7中Server类型的定义,在标号1中,Server类定义了代理类型NewMsgEventHandler(一般约定在用于事件处理时,代理类型添加EventHandler的后缀名),接着,在标号2中,定义了一个名为ProcessNewMsg的公共事件(event在此为一个上下文关键字)。一个事件必须有一个代理类型,实际上,像这样的一个事件已经是一个代理实例了,而且因为它被默认初始化为nullptr,所以它没有调用列表。
例7:
using namespace System;
public ref struct Server
{
/*1*/ delegate void NewMsgEventHandler(String^ msg);
/*2*/ static event NewMsgEventHandler^ ProcessNewMsg;
/*3*/ static void Broadcast(String^ msg)
{
if (ProcessNewMsg != nullptr)
{
ProcessNewMsg(msg);
}
}
};
当通过一条消息调用时,函数Broadcast将调用包装在ProcessNewMsg调用列表中所有的函数。
Client类定义在例8中,一个Client的类型实例无论何时被创建,它都会通过向为Server::ProcessNewMsg维护的代理列表中添加一个实例函数(它关联到实例变量),来注册它所感兴趣的新Server消息,而这是通过 += 操作符来完成,如标号5中所示。只要这个入口一直保持在通知列表中,无论何时一个新消息送达Server,注册的函数都会被调用。
例8:
using namespace System;
public ref class Client
{
String^ clientName;
/*4*/ void ProcessNewMsg(String^ msg)
{
Console::WriteLine("Client {0} received message {1}", clientName, msg);
}
public:
Client(String^ clientName)
{
this->clientName = clientName;
/*5*/ Server::ProcessNewMsg += gcnew Server::NewMsgEventHandler(this, &Client::ProcessNewMsg);
}
/*6*/ ~Client()
{
Server::ProcessNewMsg -= gcnew Server::NewMsgEventHandler(this, &Client::ProcessNewMsg);
}
};
要从通知列表中移除一个入口,可使用 -= 操作符,如标号6定义的析构函数中那样。
例9:
using namespace System;
int main()
{
Server::Broadcast("Message 1");
Client^ c1 = gcnew Client("A");
Server::Broadcast("Message 2");
Client^ c2 = gcnew Client("B");
Server::Broadcast("Message 3");
Client^ c3 = gcnew Client("C");
Server::Broadcast("Message 4");
c1->~Client();
Server::Broadcast("Message 5");
c2->~Client();
Server::Broadcast("Message 6");
c3->~Client();
Server::Broadcast("Message 7");
}
例9是主程序,一开始,没有注册任何函数,所以当发送第一个消息时,不会获得任何通知。然而,一旦构造了c1,通知列表就包含了此对象的一个入口,而接下来c2与c3的构造使这个列表增长到3个入口。在这些对象消失时(通过显式调用析构函数),入口数也相应地减少了,直到最后,一个也不剩,因此当最后一条消息发出时,没有任何对象在监听。以下是输出:
Client A received message Message 2
Client A received message Message 3
Client B received message Message 3
Client A received message Message 4
Client B receiv
|