如何从一个单独的C#程序火了事件?

我的工作的C#程序有两个独立的部件:任务创建者(TC)和任务处理器(TP)。 TC附加到不断插入新任务到一个数据库表中的Web服务。在另一方面TP从同一个表中读取并处理每一个任务,然后更新状态回到同一个表。这几乎就像一个队列,但使用数据库中完成,而不是如MSMQ。每5秒TP醒来并从表中读取检查未处理任务然而,这具有一定的性能影响。当没有新的任务,这是一个有点浪费火了一个选择从那里SQL语句。理想的方式是有某种通知方法,当新任务插入TP将得到通知,然后从梦中醒来检查是否有新的任务。

当前的解决方案:

当前解决方案的示图http://yuml.me/3b49bcfd

<强>理想的解决方案:

的idealsolution图http://yuml.me/5cf843a5

有帮助吗?

解决方案

我建议MSMQ。 :)我不知道为什么你不使用它,但是你没有提到它在你的问题。这是非常正是MSMQ是专为...应用程序之间的持久三项赛。它主要支持了基于你的“理想的解决方案”的发布/订阅消息模型......正是你所需要的:TC是出版商,TP是一个用户。 TC注册任务,然后滴在其发布队列中的消息。 TP的任务并不需要启动和运行的TC在其队列中的优先顺序到达队列成功删除消息,但是当TP任务运行时,它就会收到通知和处理的消息。

如果MSMQ是不是一种选择,你也可以使用WCF。不是的pub / sub,与WCF你可以选择一个FAF(发射后不管)消息模型。 TP将发布其TC将消耗的服务。 TC只需要触发一个消息断到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的退出循环,允许以完全结束线程不使用硬盘中止。

其他提示

  

在没有新的任务,这是一个有点浪费火起来从那里SQL语句。

一个选择

在单个表阿选择,每5秒以简单的标准以及无任何返回的行通常下一个收费落空,不担心。

<击>查看 SQL Server 2005的查询通知 。我刚刚得知,似乎它已经从SQL Server 2008拉着所以它可能不是最好的主意。

我第二是MSMQ可能是一个更好的方法。与 nServiceBus 相结合,你可以有一个赢家。

另一种方法可以是螺纹的同步事件。

在TP你可以有这样的:

EventWaitHandle taskEvent = new EventWaitHandle(true,
                EventResetMode.AutoReset,
                "newTask",
                out wasCreated);
new Thread(WaitForTask).Start();
...

public void WaitForTask() { while (true) { taskEvent.WaitOne(); ProcessTasks();} }

和在TC:

bool eventExist;
while (!eventExist)
{
    try
    {
        taskEvent= EventWaitHandle.OpenExisting("newTask");
        eventExist = true;
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        eventExist = false;
        Thread.Sleep(1000);
    }
}

CreateNewTask();
taskEvent.Set();

不,我看到的呼叫每隔5秒如何可以是这样的表现猪。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top