Como fazer programação orientada a eventos entre 2 programas separados C #?

votos
4

Como o fogo até evento de um programa separado C #?

O programa C # Eu estou trabalhando tem dois componentes separados: Criador de Tarefas (TC) e processador de tarefas (TP). TC está ligado a um serviço web que constantemente insere novas tarefas em uma tabela de banco de dados. Por outro lado TP lê da mesma tabela e processa cada tarefa, em seguida, atualiza o status de volta para a mesma mesa. É quase como uma fila, mas feito usando banco de dados, em vez de por exemplo MSMQ. Cada 5 segundos TP acorda e lê a partir da mesa para verificar se há tarefas não transformados no entanto, isso tem alguns impactos de desempenho. Quando não há novas tarefas é um pouco de resíduos ao fogo até uma instrução SQL SELECT de onde. A maneira ideal é ter algum tipo de método de notificação que, quando são inseridas novas tarefas TP será notificado e então acorda de seu sonho para verificar se há novas tarefas.

solução atual:

diagrama de solução actual http://yuml.me/3b49bcfd

solução ideal:

diagrama de idealsolution http://yuml.me/5cf843a5

Publicado 27/08/2009 em 07:42
fonte usuário
Em outras línguas...                            


3 respostas

votos
4

Eu recomendaria MSMQ. :) Eu não sou certo porque você não estiver usando-lo, porém você o mencionou na sua pergunta. Isso é muito bonito exatamente o que MSMQ foi projetado para ... CCE durável entre as aplicações. Ele suporta principalmente o / sub modelo de mensagem de pub ... que com base no seu "Ideal Solution" é exatamente o que você precisa: TC é o editor, TP é um assinante. TC registra a tarefa, em seguida, cai uma mensagem na sua fila de publicar. A tarefa TP não precisa ser instalado e funcionando para TC a cair com sucesso uma mensagem na sua fila, no entanto, quando a tarefa TP é executado, ele irá receber notificações e lidar com mensagens na fila na ordem priorizou a chegar.

Se MSMQ não é uma opção, você também pode usar WCF. Em vez de pub / sub, com o WCF você pode optar por um FAF (dispare e esqueça) modelo de mensagem. TP iria publicar um serviço que TC iria consumir. TC só precisa disparar uma mensagem de fora a serviço do TP para notificar TP de novas tarefas. A desvantagem deste modelo é que TC é dependente TP, que pode ser inferior a idéia. TP também tem de estar em execução para TC para funcionar com sucesso, uma vez que é dependente de serviço do TP. Com a aproximação MSMQ, nem TP nem TC são dependentes uns dos outros, eles são apenas dependente MSMQ (a abordagem de acoplamento inferior.)

EDITAR:

Um exemplo de como usar MSMQ para acionar eventos de TC e responder a eventos em 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;
      }
    }
  }
}

A mensagem não tem que ser um texto simples. Você pode enviar um objeto gráfico ou objeto, e ele será automaticamente ser serializado e formatado como XML por padrão. Eu acredito que você também pode serializar dados em um formato binário, se é isso que você precisa. De qualquer maneira, você vai perceber que não há chamadas Thread.sleep ou sondagem em qualquer lugar. As saídas de loop com base em um ManualResetEvent, permitindo que você terminar de forma limpa a rosca sem abortar duro.

Respondeu 27/08/2009 em 07:48
fonte usuário

votos
2

Quando não há novas tarefas é um pouco de resíduos ao fogo até uma instrução SQL SELECT de onde.

Um seleto em uma única mesa, a cada 5 segundos com critérios simples e linhas nenhum retornou normalmente custa quase nada, não se preocupe.

Respondeu 27/08/2009 em 07:51
fonte usuário

votos
2

Confira SQL Server 2005 notificações de consulta . Eu só aprendi que parece que ele foi retirado do SQL Server 2008 para que ele possa não ser a melhor idéia, afinal.

Eu segundo que MSMQ é provavelmente uma maneira muito melhor. Combinado com NServiceBus você poderia ter um vencedor.

Outra abordagem poderia ser eventos de sincronização de encadeamento.

Em TP você poderia ter algo como:

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

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

E em TC:

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

CreateNewTask();
taskEvent.Set();

Não que eu vejo como uma chamada de cada cinco segundo poderia ser um tal porco desempenho.

Respondeu 27/08/2009 em 07:49
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more