是否应该在新线程中引发事件以阻止当前的工作?

时间:2009-12-15 14:57:59

标签: .net vb.net multithreading events

我目前正在设计一个将由第三方使用的程序集。其中一个类有一个很长的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()

如果其中一个事件的处理程序需要太长时间(或者甚至更糟,它会阻塞),我看到了什么?我可以有超时时间,开发人员很难看到一个类没有正常工作,因为他的处理程序花了太长时间。

我打算在一个新线程中触发事件来避免这个问题,但这对我来说很奇怪,因为我从来没有见过这样的东西,我到目前为止看到的是开发人员产生一个新线程,如果他处理程序将耗费时间。所以问题是:

你会做什么?创建一个新线程还是强制用户创建自己的线程? (或者是一种我不知道的更好的方法吗?)

提前致谢。

6 个答案:

答案 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)

它可以是一个很好的Threadpool用法


对于一些不经常发生的事件通知,您的“Do stuff”似乎很长。你想要某种“发射并忘记”的通知,并确保被叫代表不要混淆你(他们可能需要太长时间和/或提出异常)。

  • 为每个已发布的事件创建一个线程可能会很昂贵。

  • BackgroundWorkers仅对GUI(WinForms)通知有用。

为什么不使用Threadpool?它很便宜,可以让你远离不正常的行为。