c# - 如何在 2 个独立的 C# 程序之间进行事件驱动编程?

标签 c# event-handling eai

如何从单独的 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

理想的解决方案:

diagram of idealsolution http://yuml.me/5cf843a5

最佳答案

我会推荐 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/

相关文章:

c# - 具有特殊字符和子操作的 MVC 路由参数

c# - 用作另一个 IdentityServer 的外部身份提供者的 IdentityServer 无法正确重定向

c# - Process.OutputDataReceived 在哪个线程上引发和处理?

java - Web 应用程序与第三方应用程序的集成

java - 需要将 Web 应用程序与所有主要 ERP 和 CRM 系统集成

c# - if 条件与异常处理程序

c# - 如何获取 iTextSharp.text.pdf.parser.Vector 对象的 x、y、z 值?

.net - MSMQ中是否有类似JMS Topic的等效功能?

c# - WPF 中的事件处理

jquery - 使用 jQuery 标准化 CodeMirror OnKeyEvent