我目前正在设计一个将由第三方使用的程序集。其中一个类有一个很长的TCP连接过程,它使用事件通知它的进程。例如
''# Do stuff that takes some time
RaiseEvent CompletedFirstPartEvent()
''# Do stuff that takes some time
RaiseEvent CompletedSecondPartEvent()
''# Do stuff that takes some time
RaiseEvent CompletedSecondPartEvent()
如果其中一个事件的处理程序需要太长时间(或者甚至更糟,它会阻塞),我看到了什么?我可以有超时时间,开发人员很难看到一个类没有正常工作,因为他的处理程序花了太长时间。
我打算在一个新线程中触发事件来避免这个问题,但这对我来说很奇怪,因为我从来没有见过这样的东西,我到目前为止看到的是开发人员产生一个新线程,如果他处理程序将耗费时间。所以问题是:
你会做什么?创建一个新线程还是强制用户创建自己的线程? (或者是一种我不知道的更好的方法吗?)提前致谢。
答案 0 :(得分:2)
我们在构建WebSync时遇到了同样的问题 - 如何在不牺牲应用的情况下允许用户代码中长时间运行的进程?
我们决定做的是给用户提供选项(我们的设置与您的设置不同,但前提应该有效)。基本上,允许用户告诉您是否在新线程上分离事件。
这样,如果开发人员知道他们有快速操作,他们可以避免每个事件的新线程开销,并且还可以确保事件将按特定顺序运行(否则,他们很容易就会结束由于所有事件都在不同的线程上触发,因此在自己的代码中线程化问题),但如果它们具有可能阻塞的进程,则可以指定他们需要额外的开销,并且可以自己处理任何潜在的线程问题。
在这种情况下,您只需要观察一个标志,并根据需要决定同步或在线程上触发事件。这两个世界中最好的(虽然你的结尾有点复杂)。
答案 1 :(得分:2)
我绝对不会在他们自己的线程上发射事件。让代码的消费者决定处理事情的最佳方式。
很难在没有更多细节的情况下给出明确的答案,但另一个想法是考虑事件的替代方法。也许消费者可以在他/她自己的时间消费的通知队列?让事件成为新项目添加到队列中。这让事情更加异步。消费者可以有一个单独的线程来处理队列消息。
答案 2 :(得分:1)
为什么不使用backgroundworker?
答案 3 :(得分:1)
我有一个Collector类,它打开一个“原始”套接字并从本地网络收集数据。在Collector类的内部,套接字读取由Receiver线程完成。此线程为从网络读取的每个数据包触发InternalPacketReceived事件。同样是Collector类的内部代码,我还有一个Distributor线程,它订阅了Receiver的InternalPacketReceived事件。分发服务器处理程序接收的数据包将添加到内部数据包队列中。然后,分发器线程负责使收集器的公共PacketReceived事件的订户可以使用队列中的数据包。这样,如果分配器线程被长时间运行的处理程序停止,则Receiver会继续无延迟地读取数据包。
从用户的角度来看,他正在与Collector类上的公共接口进行交互 - Start(),Stop(),订阅PacketReceived事件等。在幕后,收集器使用两个线程 - Receiver和Distributor - 来避免长时间运行的处理程序引入的问题。
我希望这很清楚。
答案 4 :(得分:1)
如果你的程序集的用户正在消耗事件并且花费太长时间来处理它们,那应该是他们要处理的问题,而不是你的问题。你无法防止愚蠢的编程。
答案 5 :(得分:1)
对于一些不经常发生的事件通知,您的“Do stuff”似乎很长。你想要某种“发射并忘记”的通知,并确保被叫代表不要混淆你(他们可能需要太长时间和/或提出异常)。
为每个已发布的事件创建一个线程可能会很昂贵。
BackgroundWorkers仅对GUI(WinForms)通知有用。
为什么不使用Threadpool?它很便宜,可以让你远离不正常的行为。