事件驱动的背景“过程”

时间:2015-04-23 11:44:12

标签: c# .net multithreading

如何实现等待其他进程引发事件的后台任务,类似于Winforms Form在引发事件之前“什么都没做”的情况?我想知道在两种情况下如何做到这一点:

  • a)作为应用程序调用的过程
  • b)作为一个应用程序中的任务

(但当然也会对一个人的答案表示赞赏。)

我现在面临的特定用法类型是让此任务处理队列(FIFO),当队列为空时 - 等待。但是请不要限制你的答案,因为我对一般答案感兴趣。

我使用了taskprocess这两个词,但也许应该使用术语thread。如果我错了,请随时纠正我。

修改

我正在寻找一些内置机制,而不是 实施 “消息泵”。最好是内置到.net,而不是必须安装的库。

2 个答案:

答案 0 :(得分:1)

在应用程序内(不是跨应用程序) - 一个简单的队列模式就可以完成,你可以使用一个线程信号机制。这是一个简单的例子:

声明一个线程安全的集合来存储你的命令,一个任务(线程池线程,有效地)来处理队列,一个信号触发器 - 以及一个允许稍后退出的标志:

private ConcurrentQueue<CommandObject> _queueCommands
private Task _queueProcessorTask; 
private AutoResetEvent _trigger;
private bool _isRunning;

初始化和启动队列处理器的代码:

_queueCommands = new ConcurrentQueue<CommandObject>();
_queueProcessorTask = new Task(ProcessQueue);

_trigger = new AutoResetEvent(false);

_isRunning = true;
_queueProcessorTask.Start();

您的队列处理器本身看起来像这样:

while (_isRunning)
{
   if (_isRunning && _queueCommands .Count != 0)
   {
       if (_queueCommands.TryDequeue(out command))
       {
           // do the job, this is FIFO
       }
   }

   // you wanna wait here, but only if there's nothing new to do
   if (_isRunning && _queueCommands.Count == 0)
   {
       _trigger.WaitOne(10000, false);
   }
}

以及一些向队列添加请求的代码:

_queueCommands.Enqueue(newCommand);
_trigger.Set();  // this is the bit which does your event / signal to spark queue processor into life

还有一个名为BlockingCollection的集合可以使用信号部分固有来实现上述功能,但我想展示这个冗长的版本,以便您知道发生了什么。

增加: 使用上面的代码,我们基本上通知专用线程它有一个要处理的消息/命令 - 所以你需要消息泵&#34;如果你愿意的话。阻塞集合以较少的步骤执行此操作,但您仍然需要向集合中添加一些内容以便&#34; pump&#34;那条消息!

答案 1 :(得分:0)

你的问题非常广泛,因此有很多好的答案是可能的。这实际上取决于你想要实现的目标。存在许多选项,您只需仔细查看您的要求并确定最适合的要求。

在大多数情况下似乎适用的基本模式是排队事件或消息处理

我将列出一些可用的&#34;开箱即用的#34;满足不同类型需求的解决方案,而不是试图将其作为详尽的清单。

跨进程

有几种&#34;预煮&#34;例如,如果您在多个流程中进行事件/消息传递,则可以使用这些解决方案。

如果您需要某种形式的持久消息传递,您可以查看其中一种消息总线实现,例如: NServiceBus Kafka ,...

如果您的消息需要快速但不需要持久性,那么如果您想在.NET Web上执行此操作,那么支持多种消息传递模式的 0mq 等内容可能会很有用应用,您可能需要查看 SignalR

如果您要进行任何类型的复杂事件处理,或者您希望拥有事件的永久记忆并执行&#34;计算&#34;,例如聚合或其他对一系列事件的预测类型,您可以查看 EventStore 项目。

如果您想做一些简单的事情,比如数据库中的数据发生变化时收到通知,您可以查看特定类型数据库的特定更改通知服务/触发类似物(例如RavenDB&#39的更改API)。 / p>

在流程

如果您需要在单个进程中的线程之间执行(非持久)消息传递,那么最完整的两个&#34;预烘焙&#34;

是您可以使用的构建块
  • <强> TPL Dataflow 允许设置特定的数据处理管道,具有多个缓冲和转换选项(想想管道和过滤器)。

  • <强> Reactive extensions 特别用于构建非持久异步事件处理,使用可观察序列和LINQ样式查询运算符组合和转换事件。

如果您的需求比他们提供的要简单得多,您可以构建自己的需求,同时考虑到已经提到的解决方案中使用的基本类型的经过测试的模式。