如何从单独的 C# 程序中触发事件?
我正在处理的 C# 程序有两个独立的组件:Task Creator (TC) 和 Task Processor (TP)。 TC 附加到一个不断向数据库表中插入新任务的 Web 服务。另一方面,TP 从同一个表中读取并处理每个任务,然后将状态更新回同一个表。它几乎就像一个队列,但使用数据库而不是例如队列完成。 MSMQ。每 5 秒 TP 唤醒并从表中读取以检查未处理的任务,但这会对性能产生一些影响。当没有新任务时,启动 select from where SQL 语句有点浪费。理想的方式是有某种通知方式,当有新任务插入时,TP会得到通知,然后从梦中醒来,检查是否有新任务。
当前解决方案:
diagram of current solution http://yuml.me/3b49bcfd
理想的解决方案:
最佳答案
我会推荐 MSMQ。 :) 我不确定您为什么不使用它,但是您确实在问题中提到了它。这几乎正是 MSMQ 的设计目的......应用程序之间的持久事件。它主要支持 pub/sub 消息模型......基于您的“理想解决方案”正是您所需要的:TC 是发布者,TP 是订阅者。 TC 注册任务,然后将消息放入其发布队列中。 TP 任务不需要启动并运行,TC 就可以成功地将消息放入其队列中,但是当 TP 任务运行时,它将接收通知并按照到达的优先顺序处理队列中的消息。
如果 MSMQ 不是一个选项,您也可以使用 WCF。使用 WCF,您可以选择 FAF(即发即忘)消息模型,而不是发布/订阅。 TP 将发布 TC 将使用的服务。 TC 只需要向 TP 的服务发送消息以通知 TP 有新任务。该模型的缺点是 TC 依赖于 TP,这可能不太理想。 TP 也必须运行 TC 才能成功运行,因为它依赖于 TP 的服务。使用 MSMQ 方法,TP 和 TC 都不相互依赖,它们只依赖于 MSMQ(一种较低耦合的方法。)
编辑:
如何使用 MSMQ 从 TC 触发事件并响应 TP 中的事件的示例。
// TC message queue manager, sends messages
public class TaskMessageQueueManager
{
public void NotifySubscribersOfNewTasks()
{
var queue = getQueue(".\private$\TaskNotifications");
queue.Send("Tasks waiting.");
}
private MessageQueue getQueue(string name)
{
MessageQueue queue = null;
try
{
if (!MessageQueue.Exists(name))
{
queue = MessageQueue.Create(name);
}
else
{
queue = new MessageQueue(name);
}
}
catch (Exception ex)
{
throw new InvalidOperationException("An error occurred while retrieving the message queue '" + name + "'.", ex);
}
return queue;
}
}
// TP message queue handler, receives messages
public class TaskMessageQueueHandler
{
private Thread m_thread;
private ManualResetEvent m_signal;
public void Start()
{
m_signal = new ManualResetEvent(false);
m_thread = new Thread(MSMQReceiveLoop);
m_thread.Start();
}
public void Stop()
{
m_signal.Set();
}
private void MSMQReceiveLoop()
{
bool running = true;
MessageQueue queue = getQueue(".\private$\TaskNotifications");
while (running)
{
try
{
var message = queue.Receive(); // Blocks here until a message is received by MSMQ
if (message.Body.ToString() == "Tasks waiting.")
{
// TODO: Fire off process, perhaps another thread, to handle waiting tasks
}
if (m_signal.WaitOne(10)) // Non-blocking check for exit signal
{
running = false; // If Stop method has been called, the signal will be set and we can end loop
}
}
catch
{
// handle error
running = false;
}
}
}
}
消息不必是简单的文本。您可以发送对象或对象图,默认情况下它将自动序列化并格式化为 XML。我相信您也可以以二进制格式序列化数据,如果您需要的话。无论哪种方式,您都会注意到任何地方都没有 Thread.Sleep 调用或轮询。循环基于 ManualResetEvent 退出,允许您干净地结束线程而无需硬中止。
关于c# - 如何在 2 个独立的 C# 程序之间进行事件驱动编程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1339243/