Domanda

Come accendere evento da un programma separato C #?

Il programma C # Sto lavorando a due componenti separati: Task Creatore (TC) e la Task Processor (TP). TC è collegato a un servizio web che inserisce continuamente nuovi compiti in una tabella del database. D'altra parte TP legge dalla stessa tabella ed elabora ogni attività poi aggiorna lo stato di nuovo allo stesso tavolo. E 'quasi come una coda, ma fatto utilizzando database anziché per esempio MSMQ. Ogni 5 secondi TP si sveglia e legge dal tavolo per verificare la presenza di attività non trasformati tuttavia questo ha qualche impatto sulle prestazioni. Quando non ci sono nuovi compiti è un po 'di rifiuti di accendere una selezione da cui SQL. Il modo ideale è quello di avere un qualche tipo di metodo di notifica che, quando nuovi compiti vengono inseriti TP otterrà una notifica e poi si sveglia dal suo sogno di verificare la presenza di nuovi compiti.

soluzione attuale:

diagramma della soluzione corrente http://yuml.me/3b49bcfd

Soluzione ideale:

diagramma di idealsolution http://yuml.me/5cf843a5

È stato utile?

Soluzione

mi sento di raccomandare MSMQ. :) Io non sono sicuro perché non lo si utilizza, ma lei non ha citato nella sua interrogazione. Questo è più o meno esattamente quello MSMQ è stato progettato per ... eventing durevole tra le applicazioni. Sostiene in primo luogo il modello di messaggio / sub pub ... che ha basato sul "soluzione ideale" è esattamente quello che vi serve: TC è l'editore, TP è un abbonato. TC registra l'attività, quindi scende un messaggio nella sua coda di pubblicare. Il compito TP non ha bisogno di essere installato e funzionante per TC a goccia con successo un messaggio nella sua coda, tuttavia quando il compito TP è in esecuzione, riceverà le notifiche e gestire i messaggi in coda secondo l'ordine prioritario l'arrivo.

Se MSMQ non è un'opzione, è possibile utilizzare anche WCF. Invece di pub / sub, con WCF si potrebbe optare per un FAF (fuoco e dimenticare) modello di messaggio. TP avrebbe pubblicato un servizio che TC consumerebbe. TC avrebbe solo bisogno di sparare un messaggio via al servizio di TP per notificare TP di nuovi compiti. Lo svantaggio di questo modello è che TC dipende TP, che potrebbe essere inferiore idea. TP deve anche essere in esecuzione per TC per funzionare con successo, dal momento che dipende il servizio di TP. Con l'approccio MSMQ, né TP né TC sono dipendenti l'una dall'altra, che dipendono solo su MSMQ (approccio-giunto inferiore.)

EDIT:

Un esempio di come utilizzare MSMQ per generare gli eventi da TC e rispondere agli eventi in 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;
      }
    }
  }
}

Il messaggio non deve essere semplice testo. È possibile inviare un oggetto grafico o un oggetto, e si verrà automaticamente serializzato e formattati in formato XML per impostazione predefinita. Io credo che si possa anche serializzare i dati in un formato binario, se questo è quello che vi serve. In entrambi i casi, si noterà che non ci sono chiamate Thread.Sleep o polling ovunque. Il ciclo si interrompe sulla base di un ManualResetEvent, che consente di terminare in modo pulito il filo senza interruzione dura.

Altri suggerimenti

  

Quando non ci sono nuovi compiti è un po 'di rifiuti di accendere una selezione da cui SQL.

Un selezionato su una singola tabella, ogni 5 secondi con criteri semplici e nessuno righe restituite solito costa quasi nulla, non vi preoccupate.

Scopri SQL Server 2005 notifiche delle query . Ho appena saputo che sembra che è stato tirato da SQL Server 2008 quindi potrebbe non essere la migliore idea, dopo tutto.

I secondi che MSMQ è probabilmente un modo molto migliore. In combinazione con NServiceBus si potrebbe avere un vincitore.

Un altro approccio potrebbe essere eventi di sincronizzazione filetto.

In TP si potrebbe avere qualcosa di simile:

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

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

E in TC:

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

CreateNewTask();
taskEvent.Set();

Non che io vedo come una chiamata ogni cinque secondi potrebbe essere un tale porco prestazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top