【问题标题】:Is it OK to ask handlers of my events return immediately?可以要求我的事件的处理程序立即返回吗?
【发布时间】:2013-12-02 11:02:20
【问题描述】:

我正在编写一个 .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...
    }
}

【问题讨论】:

  • 我想真正的问题是,您还有哪些其他选择?
  • 我想可以 BeginInvoke() 它在另一个线程(可能是线程池)上,或者我可以隐藏事件并让客户端定期轮询已经发生的事件..
  • 看起来线程池可以在这里工作。虽然我不明白这个网络库是如何工作的。如果那是一些公共 API,那么为什么不使用 wcf 并让它管理远程调用呢?
  • @Artjom 是的 - 但也许它现在要求更多用户编写线程安全代码!我不使用 WCF 的原因有很多,我不在乎详细说明!
  • 我想起了 Windows 的情况,它从 Cooperative multitasking 切换到 Pre-emptive multitasking 因为,嗯,开发人员不擅长与他人相处......

标签: c# .net events design-patterns event-handling


【解决方案1】:

要求我的事件的处理程序立即返回可以吗?

是的。

您应该在文档中明确说明如果订阅者不及时返回,该库将无法正常运行。

你不应该强制执行它

为什么?因为你说你正在开发一个图书馆。与框架相反,库让用户处于控制之中。因此,用户决定在订阅您的事件时做他们想做的事。

强制处理程序快速只会增加复杂性,使库更难使用。这就是为什么我认为最好明确预期,如果由于处理程序缓慢而让用户遇到问题,只需将其推荐给文档即可。

【讨论】:

    【解决方案2】:

    如果处理程序快速返回对您的代码至关重要,则应将其构建在允许您取消处理程序的结构上。由于事件处理程序不允许您取消处理程序的执行,例如在超时之前,您有以下选择:

    • 使用事件处理程序并接受您对调用者的操作没有任何控制权。当然,您可以要求来电者在特定时间范围内返回,但您应该做好准备,有时他们不会。但是,您可以构造您的代码,以便在代码中对时间不重要的位置调用事件处理程序(例如,在您的示例中将“时间重要的东西”移动到 raise 前面)或使用线程来允许并行执行。
    • 如果您不需要事件的特殊特性(例如订阅模型、多个处理程序的订阅),您可以使用允许您取消处理程序的替代方法。根据您使用的框架版本,替代方法可能是使用调用者提供给您的类的Task,类似于回调函数。任务允许您在特定的毫秒数内 Wait 完成任务。

    【讨论】:

    • 我已将“是的,没关系”标记为答案,因为我认为这是 MS 所做的,例如在基于事件的 UI 中,处理程序在 UI 线程上同步调用并期望快速返回。尽管如此,您已经根据具体情况展示了值得考虑的有效替代方法 - 希望我也可以将其标记为答案!
    【解决方案3】:

    我个人认为这是一个坏主意 - 因为 Windows 不是实时操作系统。在非实时操作系统中,您不能指望某些方法执行 0.5 秒。

    【讨论】:

    • 0.5 秒?你到底是从哪里弄来的号码的?听起来像是我的第一台计算机能够做到的事情(IBM XT 兼容)
    • 0.5 秒 - 来自主题。您能否在您的 IBM 上保证在某些事件发生后您的操作系统启动某个线程所需的时间少于 0.5 秒?如果当时正在进行一些繁重的计算?您无法确定这一点,因为 Windows 不会将任务\事件安排为实时操作系统。显然应该有一些超时,但 500 毫秒更像是“实时”间隔。
    • @nikita 我正在同步调用事件,而不是启动新线程。虽然我永远不会将 500 毫秒称为“实时”,但您可以在那个时间段内将数据包网络连接到世界各地,但我想说几微秒是“实时”的,尽管“实时”可以是任何时间,只要最大时间总是被称为一个硬性和快速的值,尽管这已经离题了......
    • @nikita 虽然我同意你的观点,但操作系统只能让我的线程 CPU 时间在未来的任何时候运行,但是我已经测试并且熟悉我在做什么,这是快节奏的应用程序- 这样的超时很好。
    猜你喜欢
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多