在一个线程中引发事件以调用第二个线程中的方法
我正在开发一个程序,该程序对来自互联网套接字的事件做出反应,也可能对来自计时器的事件做出反应。使用两个线程似乎很自然:
- 一个用于主程序,
- 第二个用于侦听套接字、解析输入并引发适当的事件。
附加要求:
- 应用程序不应依赖于 UI 线程(它可以作为控制台应用程序运行)。
- 主程序应该同步处理消息,即按照消息到达的顺序。
- 主线程不得在等待计时器时阻塞(我想这意味着我必须在不同的线程上运行计时器)。
现在有一些问题:-):
- 我猜要求#1意味着我没有内置消息泵,所以我无法从套接字监听器使用
Invoke()
/计时器线程。这是正确的吗? - 如何安全地在一个线程(例如侦听器)上引发事件,并让订阅者在另一个线程(主线程)上同步运行?
- 在后续处理程序完成之前很可能会引发新事件。在这种情况下会发生什么?该事件会被 CLR 缓冲到某个地方,还是会被忽略?
最后但并非最不重要的一点是:我想我的目标是消息生产者/消费者范例的并行,但我想使用事件而不是消息。您认为有更好的方法吗?
谢谢,
Boaz
编辑
我想首先解释一下我使用事件的动机。该应用程序是一个自动交易引擎,必须响应市场上发生的事件(例如股票价格的变化)。当发生这种情况时,主线程上可能有多个订阅者应该被调用,这是使用事件的经典场景。
我想我总是可以将生产者/消费者与一些消息队列一起使用,并让消费者在主线程上引发事件,但我认为可能有更直接的方法。
I'm working on a program which reacts to events coming from an internet socket, and possibly from timers as well. It seems natural to use two threads:
- One for the main program
- A second one which listens to the socket, parses the input, and raises an appropriate event.
Additional requirements:
- The application should not rely on a UI thread (it may be run as a console application).
- The main program should process messages synchronously, i.e. in the order in which they arrived.
- The main thread must not block on waiting for timers (I guess this means I have to run timers on different threads).
And now for some questions :-):
- I'm guessing requirement #1 means that I don't have a built-in message pump, so I can't use
Invoke()
from the socket listener / timer threads. Is this correct? - How can I safely raise events on one thread (e.g. the listener), and have the subscribers run synchronously on another (the main thread)?
- It is very likely that new events will be raised before the subsequent handler is done. What will happen in this case? Will the event be buffed somewhere by the CLR, or will it be ignored?
And last but not least: I guess I'm aiming for the parallel for the message Producer/Consumer paradigm, but instead of messages, I want to use events. Do you think there is a better approach?
Thanks,
Boaz
EDIT
I want to explain my motivation for using events in the first place. The application is an automated trading engine which has to respond to events that happen in the market (e.g. a change in the price of a stock). When this happens, there may be multiple subscribers on the main thread which should be invoked, which is a classical scenario to use events.
I guess I can always use the Producer/Consumer with some message queue, and have the consumer raise events on the main thread, but I figured there might be a more direct way.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为使用消息将是最简单的方法。如果您使用 C# 4,这会非常简单,这要归功于 BlockingCollection<> 。
因此,有一个共享的 BlockingCollection,其中 Message 是您的消息类。
然后在你的工作线程中你这样做
就是这样。
GetConsumingEnumerable() 将阻塞,直到有消息要处理。然后它将从队列中删除该消息,并且您的循环将处理它。
这样做的好处是您可以添加更多线程,并且在每个线程中只有 foreach 循环。
完成后,调用blockingCollection.CompletedAdding();
顺便说一句,队列处理并发并将同时发送的消息排队等。
希望这对
安德烈有帮助
I think using messages will be the simplest way. If you are using C# 4 this is very easy thanks to the BlockingCollection<>
So have a shared BlockingCollection, where Message is your message class.
Then in your worker thread you do this
That is it.
The GetConsumingEnumerable() will block until there is a message to process. It will then remove the message from the queue and your loop will process it.
What is nice about this is that you can add more threads and in each one you just have the foreach loop.
When you are done call blockingCollection.CompletedAdding();
BTW the queue handles concurrency and will queue messages sent at the same time etc.
Hope this helps
Andre
您可以在线程之间实现共享队列。每当引发事件时,您都可以将其推送到队列中。主线程是一个无限循环,它检查新事件,将它们从队列中删除,处理事件,当没有更多事件时,它会休眠一段时间。
You could implement a shared queue between your threads. Whenever an event is raised you could push it in the queue. The main thread is an endless loop that checks for new events, removes them from the queue, handles the event and when there are no more events it sleeps for some time.