简体   繁体   English

在一个线程中引发事件以调用第二个线程中的方法

[英]Raise event in one thread to invoke methods in a second thread

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: 其他要求:

  1. The application should not rely on a UI thread (it may be run as a console application). 应用程序不应该依赖UI线程(它可以作为控制台应用程序运行)。
  2. The main program should process messages synchronously, ie in the order in which they arrived. 主程序应该同步处理消息,即按照它们到达的顺序。
  3. 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 :-): 现在有些问题:-):

  1. 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. 我猜测需求#1意味着我没有内置消息泵,所以我不能使用套接字监听器/定时器线程中的Invoke() Is this correct? 它是否正确?
  2. How can I safely raise events on one thread (eg the listener), and have the subscribers run synchronously on another (the main thread)? 如何在一个线程(例如监听器)上安全地引发事件,并让订户在另一个线程(主线程)上同步运行?
  3. 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? CLR会在某个地方对事件进行缓冲,还是会被忽略?

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 (eg 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. 我想我总是可以使用Producer / Consumer和一些消息队列,并让消费者在主线程上引发事件,但我认为可能有更直接的方式。

I think using messages will be the simplest way. 我认为使用消息将是最简单的方法。 If you are using C# 4 this is very easy thanks to the BlockingCollection<> 如果你使用的是C#4,这要归功于BlockingCollection <>

So have a shared BlockingCollection, where Message is your message class. 所以有一个共享的BlockingCollection,其中Message是你的消息类。

Then in your worker thread you do this 然后在你的工作线程中你这样做

var msgEnum = blockingCollection.GetConsumingEnumerable();

//Per thread
foreach( Message message in msgEnum )
{
   //Process messages here
}

That is it. 这就对了。

The GetConsumingEnumerable() will block until there is a message to process. GetConsumingEnumerable()将阻塞,直到有消息要处理。 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. 这有什么好处,你可以添加更多的线程,每个线程都有foreach循环。

When you are done call blockingCollection.CompletedAdding(); 完成后调用blockingCollection.CompletedAdding();

BTW the queue handles concurrency and will queue messages sent at the same time etc. BTW队列处理并发并将队列消息同时排队等。

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. 主线程是一个无限循环,它检查新事件,从队列中删除它们,处理事件,当没有更多事件时,它会休眠一段时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM