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

时间:2011-05-17 07:10:55

标签: c# multithreading events

我正在开发一个程序,它可以响应来自互联网套接字的事件,也可能来自定时器。使用两个线程似乎很自然:

  • 一个主程序
  • 第二个侦听套接字,解析输入并引发适当的事件。

其他要求:

  1. 应用程序不应该依赖UI线程(它可以作为控制台应用程序运行)。
  2. 主程序应同步处理消息,即按照它们到达的顺序处理。
  3. 主线程在等待定时器时不能阻塞(我想这意味着我必须在不同的线程上运行定时器)。
  4. 现在提出一些问题: - ):

    1. 我猜测需求#1意味着我没有内置消息泵,因此我无法使用套接字侦听器/计时器线程中的Invoke()。这是对的吗?
    2. 如何在一个线程(例如侦听器)上安全地引发事件,让订阅者在另一个线程(主线程)上同步运行?
    3. 在后续处理程序完成之前,很可能会引发新事件。在这种情况下会发生什么? CLR会在某个地方对事件进行缓冲,还是会被忽略?
    4. 最后但并非最不重要:我想我的目标是消息生产者/消费者范例的并行,但我想使用事件而不是消息。你认为有更好的方法吗?

      谢谢,

      波阿斯

      修改

      我想先解释一下我使用事件的动机。该应用程序是一个自动交易引擎,必须响应市场中发生的事件(例如股票价格的变化)。发生这种情况时,主线程上可能有多个订阅者应该被调用,这是使用事件的经典场景。

      我想我总是可以将Producer / Consumer与一些消息队列一起使用,并让消费者在主线程上引发事件,但我认为可能有更直接的方式。

2 个答案:

答案 0 :(得分:4)

我认为使用消息将是最简单的方法。如果您使用的是C#4,这要归功于BlockingCollection<>

所以有一个共享的BlockingCollection,其中Message是你的消息类。

然后在你的工作线程中执行此操作

var msgEnum = blockingCollection.GetConsumingEnumerable();

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

就是这样。

GetConsumingEnumerable()将阻塞,直到有消息要处理。然后它将从队列中删除该消息,您的循环将处理它。

这有什么好处,你可以添加更多的线程,每个线程都有你的foreach循环。

完成后,请调用blockingCollection.CompletedAdding();

BTW队列处理并发并将同时发送的消息排队等。

希望这有帮助

安德烈

答案 1 :(得分:2)

您可以在线程之间实现共享队列。每当引发事件时,您都可以将其推入队列中。主线程是一个无限循环,它检查新事件,将它们从队列中删除,处理事件以及何时没有更多事件它会休眠一段时间。