Han*_*ant 11
这是一个非常广泛的主题,我只能合理地涵盖基础知识.这些机制并非特定于.NET,它们适用于在Windows上运行的任何程序.操作系统或其他程序可以通过两种基本方式触发事件.
第一个是你假设的,按钮的Click事件的基础机制以及几乎所有与GUI程序相关的事件.核心.NET调用是Application.Run(),它启动一个调度程序循环.也称为"抽取消息循环".生产者 - 消费者问题的一般解决方案.生成事件的基本winapi函数是SendMessage()和PostMessage()..NET程序具有管道,可以在您可以订阅的事件中转换这些消息,NativeWindow类就是一个很好的例子.它的WndProc()方法在收到消息时运行.然后,它可以根据特定消息提出特定事件.
第二个是操作系统可以对任意工作线程上的函数进行回调的地方,通常是从线程池中提取的一个函数.FileSystemWatcher就是那个例子,设置它的底层winapi函数是ReadDirectoryChangesW().它支持重叠I/O,允许它异步操作.换句话说,您可以要求它开始工作并立即返回.然后,操作系统发出事件信号或在作业完成时进行回调.这种事件的工作方式隐含的是,它们在任意线程上被触发,与第一种机制不同.
了解所有这些,有必要了解有关winapi的更多信息.
TL; DR:事件监听器实际上不必主动收听; 他们被事件触发方召回.请参阅观察者模式.
就像属性一样,实际上只不过是一组方法和一些语法糖,.NET事件也不仅仅是其他东西(多播委托)和一些语法糖.
就像属性一样,你可以通过语言自动实现(例如string Name { get; set; })事件通常也以非常类似的方式"自动实现"(除非你自己专门实现一个事件).如果你想自己实现一个事件(这是非常罕见的事情),它可能看起来像这样(简化):
public event Action Completed
{
add // gets called for each `obj.Completed += value;`
{
if (completed == null)
{
completed = new Action(value);
}
else
{
completed += value;
}
}
remove // gets called for each `obj.Completed -= value;`
{
if (completed != null)
{
completed -= value;
}
}
}
private Action completed; // backing field (a delegate) for the event
Run Code Online (Sandbox Code Playgroud)
与大多数数据属性一样,每个事件通常也有一个支持字段 - 即多播委托.订阅事件(Completed += …)或从中取消订阅(-=)会转换为对调用者add和remove访问者方法的调用.
(多播)委托具有内部方法调用列表.您可以通过+=运算符添加方法(如上面发生在add访问器内部)或通过-=运算符从调用列表中删除它(如上面的remove访问器中所示).因此,需要注意的是+=,并-=取决于它们是否应用于事件(所调用做不同的事情add或remove)或委托(添加/通过在引擎罩调用删除内部调用列表的方法Delegate.Combine和Delegate.Remove).
活动订阅者不必轮询; 触发事件时会调用它们.无论什么方提出/触发事件实际上只是调用"后备字段"代表; 并且调用该委托意味着调用委托的调用列表上的每个方法 - 即订阅者的事件处理程序方法.
| 归档时间: |
|
| 查看次数: |
824 次 |
| 最近记录: |