C#事件订阅发布实现原理详解
一、事件订阅发布机制简介
事件是C#中最常用的一种机制之一,它可以将对象之间的通信极大地简化和解耦。订阅和发布是事件发生的关键步骤,其中订阅(或称为注册)表示一个对象准备接收来自另一个对象(即发布者)的通知,而发布(或称为引发)则表示对象触发了一个事件并向订阅该事件的其他对象发送通知。
在C#中,此机制通过event
关键字来实现。当一个事件被声明为event
时,它本质上是一个特殊的委托,而事件的引发则是通过委托的执行来实现的。因此,订阅者需要将它们的方法添加到事件的委托列表中,而发布者在事件被引发时将向该列表中的每个订阅者发送通知。
二、订阅发布机制的实现原理
事件的订阅和发布实现有多种方式,本文将介绍使用C#中的委托和事件机制实现订阅发布的方法。订阅发布机制的实现步骤如下:
1. 定义事件
在C#中,可以通过event
关键字定义事件。例如:
public delegate void EventHandler(object sender, EventArgs e);
public class SomePublisher
{
public event EventHandler SomeEvent;
}
以上代码定义了一个名为SomeEvent
的事件,并将其类型定义为EventHandler
,即一个具有两个参数(object
类型和EventArgs
类型)和无返回值的委托。在SomePublisher
类中使用event
关键字定义SomeEvent
事件,并标识为公共事件,以允许其他类将其订阅。
2. 发布事件
发布(或引发)事件是通过调用类中的事件函数来实现的。例如:
public void DoSomething()
{
OnSomeEvent(this, EventArgs.Empty);
}
protected virtual void OnSomeEvent(object sender, EventArgs e)
{
SomeEvent?.Invoke(sender, e);
}
以上代码展示了在SomePublisher
类中如何发布事件。在DoSomething
方法中调用OnSomeEvent
函数,将传递this
作为调用者(即发布者),以及一个空的EventArgs
参数(也可以使用自定义的事件参数类型)。OnSomeEvent
方法是一个虚拟方法,允许派生类覆盖此方法以提供自己的实现。在其默认实现中,该方法使用条件运算符检查SomeEvent
是否为空,以避免在无订阅事件的情况下引发空引用异常。如果SomeEvent
不为空,则使用委托的Invoke方法向委托列表中的每个订阅者发送通知。
3. 订阅事件
订阅事件是将订阅者的方法添加到事件委托列表中的过程。以下是一个简单的示例:
public class SomeSubscriber
{
public void SubscribeTo(SomePublisher publisher)
{
publisher.SomeEvent += HandleSomeEvent;
}
public void UnsubscribeFrom(SomePublisher publisher)
{
publisher.SomeEvent -= HandleSomeEvent;
}
private void HandleSomeEvent(object sender, EventArgs e)
{
Console.WriteLine("Some event occurred.");
}
}
以上代码展示了一个名为SomeSubscriber
的订阅者类,它定义了两个公共方法:SubscribeTo
和UnsubscribeFrom
,允许它将自己添加到和从订阅列表中删除。HandleSomeEvent
方法是SomeEvent
事件的处理函数,它将在事件被引发时执行。
三、示例说明
下面通过两个示例来说明事件订阅发布机制的使用方法。
示例1:使用事件机制实现线程通信
using System;
using System.Threading;
namespace EventDemo
{
class Program
{
static void Main(string[] args)
{
var instance = new EventDemo();
Thread thread = new Thread(delegate() { instance.DoWork(); });
thread.Start();
while (true)
{
Console.ReadLine();
instance.Cancel();
}
}
}
public class EventDemo
{
public event EventHandler Done;
private bool _cancelled;
public void DoWork()
{
int count = 0;
while (!_cancelled && count < 10)
{
count++;
Console.WriteLine("Working... " + count);
Thread.Sleep(1000);
}
if (!_cancelled)
{
OnDone(new EventArgs());
}
Console.WriteLine("Work done.");
}
protected virtual void OnDone(EventArgs e)
{
Done?.Invoke(this, e);
}
public void Cancel()
{
Console.WriteLine("Cancelling...");
_cancelled = true;
}
}
}
以上示例展示了如何使用事件机制实现线程之间的通信。在EventDemo
类中定义了一个名为Done
的事件,表示已完成某项任务。在DoWork
方法中,执行一些工作,如果_cancelled
字段为false
,则在工作完成时引发Done
事件。为终止工作,我们可以在控制台上按回车键,然后调用Cancel
方法来设置_cancelled
字段为true
,以立即取消操作。
在程序的主线程中,我们使用委托来开启一个新线程,开始执行DoWork
方法。之后我们进入一个无限循环,等待在控制台上输入回车,然后结束工作并关闭线程。
示例2:使用事件机制实现对象通信
using System;
namespace EventDemo
{
class Program
{
static void Main(string[] args)
{
var publisher = new SomePublisher();
var subscriber1 = new SomeSubscriber("Subscriber 1");
var subscriber2 = new SomeSubscriber("Subscriber 2");
subscriber1.SubscribeTo(publisher);
subscriber2.SubscribeTo(publisher);
publisher.DoSomething();
subscriber1.UnsubscribeFrom(publisher);
publisher.DoSomething();
}
}
public delegate void EventHandler(object sender, EventArgs e);
public class SomePublisher
{
public event EventHandler SomeEvent;
public void DoSomething()
{
OnSomeEvent(this, EventArgs.Empty);
}
protected virtual void OnSomeEvent(object sender, EventArgs e)
{
SomeEvent?.Invoke(sender, e);
}
}
public class SomeSubscriber
{
private string _name;
public SomeSubscriber(string name)
{
_name = name;
}
public void SubscribeTo(SomePublisher publisher)
{
publisher.SomeEvent += HandleSomeEvent;
}
public void UnsubscribeFrom(SomePublisher publisher)
{
publisher.SomeEvent -= HandleSomeEvent;
}
private void HandleSomeEvent(object sender, EventArgs e)
{
Console.WriteLine(_name + " received event.");
}
}
}
以上示例展示了如何使用事件机制实现简单的对象通信。在这个例子中,SomePublisher
类定义了一个名为SomeEvent
的事件,表示某些事件已发生。在DoSomething
方法中,当操作完成时,将引发SomeEvent
事件。SomeSubscriber
类定义了一个构造函数,它允许为Subscriber
指定名称,并且提供两个公共方法,SubscribeTo
和UnsubscribeFrom
,允许它将自己添加到和从订阅列表中删除。在HandleSomeEvent
方法中,订阅者将收到事件并输出消息。
在程序的主线程中,我们创建一个SomePublisher
对象和两个SomeSubscriber
对象。两个订阅者都将publisher
实例的SomeEvent
事件添加到其订阅列表中。在调用publisher
的DoSomething
方法时,两个订阅者的HandleSomeEvent
方法都将被调用,并且两个订阅者将输出消息。之后,我们取消第一个订阅者,再次调用publisher
的DoSomething
方法,只有第二个订阅者的HandleSomeEvent
方法将被调用,输出消息。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#事件订阅发布实现原理详解 - Python技术站