我正在编写一个.NET库。其中一个类具有库用户需要订阅的事件。是否可以要求这些事件的处理程序的实现快速返回?还是这是一个有共同解决方案的共同问题?
(如果处理程序花了很长时间,这不会是致命的,但如果他们的处理程序花的时间超过半秒,事情就会开始出错——这是一个网络库,连接的对等方会认为这个对等方已经删除,因为在发送回复的同一线程上引发了事件)
例如
public delegate void Ping();
class A
{
/// <summary>
/// If your handler doesn't return quickly... I am going to cry.
/// </summary>
public event Ping Ping;
private void RaisePing()
{
var handler = Ping;
if(handler != null)
handler();
}
// this is called several times a secound
private void MainLoop()
{
if(something)
RaisePing();
// time important stuff - musn't take long to get here...
}
}
可以要求我的事件处理程序立即返回吗?
是的。
您应该在文档中明确声明,如果订阅者没有及时返回,库将无法正常工作。
您不应该强制执行
为什么?因为你说你正在开发一个图书馆。与框架相反,库由用户来控制。因此,当用户订阅您的活动时,他们可以决定做他们想做的事情。
强制处理程序快速只会增加复杂性,使库更难使用。这就是为什么我认为最好明确预期,如果用户因为处理速度慢而遇到问题,就让他们参考文档。
如果处理程序快速返回对代码至关重要,那么应该在允许取消处理程序的结构上构建它。由于事件处理程序不允许您取消处理程序的执行,例如通过超时,您有以下选项:
- 使用事件处理程序并接受您对调用方的操作没有任何控制。当然,你可以要求呼叫者在特定的时间范围内返回,但你应该做好准备,有时他们不会。然而,您可以对代码进行结构化,以便在代码中不具有时间关键性的位置调用事件处理程序(例如,在您的示例中,将"时间重要的东西"移到提升前面),或者使用线程来允许并行执行
- 如果您不需要事件的特殊特性(例如订阅模型、订阅多个处理程序),则可以使用允许取消处理程序的替代方法。根据您使用的Framework版本,另一种选择可能是使用调用方提供给类的Task,类似于回调函数。任务允许您等待特定的毫秒数以完成任务
我个人认为这是个坏主意,因为Windows不是实时操作系统。在非实时操作系统中,不能指望某些方法能执行0.5秒。