2012-02-23 10 views
12

Ho due applicazioni .net che vengono eseguite sulla stessa macchina. La prima applicazione è il 'Motore'. Costruisce immagini - la dimensione dell'immagine è di circa 4M. La seconda applicazione è il 'Visualizzatore'. Mostra le immagini inviate dal 'Motore'. Il motore invia le immagini ogni 10-15 secondi.Trasferimento di dati di grandi dimensioni tra le applicazioni .net sullo stesso computer

La mia domanda è qual è il modo migliore per passare le immagini dal motore al visualizzatore. Attualmente sto usando FileSystem per questo. Il motore scrive l'immagine nella cartella del file system e il visualizzatore ottiene questo file usando FileSystemWatcher.

Questo approccio è ok? È affidabile?

+0

Essere pedanti qui ... i propri test di unità dovrebbero dimostrare se è sia corretto che affidabile. –

+0

@AdamHouldsworth Non ho notato che l'OP dice che stanno addirittura utilizzando i test unitari. Ciò significa che anche questa affermazione era in qualche modo irrilevante. –

+0

@ Mr.Disappointment Non proprio. I test unitari andrebbero a dimostrare l'affidabilità e il successo funzionale dell'approccio - i capisaldi della domanda. Anche il punto fondamentale era che se non stavano usando i test unitari per provare questa roba, dovrebbero esserlo. –

risposta

5

C'è certo numero di buone opzioni:

  • Message Queue
  • Named Pipes (direttamente)
  • File mappati memoria
  • WCF su Nome Pipes o MSMQ

Uno di questi è più che abbastanza veloce, quindi suggerirei più facile da implementare.

La coda messaggi (MSMQ) secondo me è la più semplice da utilizzare, fornisce trasferimento oggetto (anziché flussi) e offre una persistenza di trasporto opzionale (utile nel caso in cui il mittente o il destinatario non sia in esecuzione). Tutto questo è vero per WCF su MSMQ ma WCF significa più overhead, complessità e configurazione coinvolte e nessun valore aggiuntivo (in questo caso).

Invia come questo:

MessageQueue queue = new MessageQueue(".\\private$\\ImagesQueue"); 
Message msg = new Message 
{ 
    Formatter = new BinaryMessageFormatter(), 
    Body = myImage, 
    Label = "Image" 
}; 
queue.Send(msg); 

ricezione:

MessageQueue queue = new MessageQueue(".\\private$\\ImagesQueue"); 
msg = queue.Receive(TimeSpan.FromMilliseconds(100)); 
if (msg != null) 
{ 
    msg.Formatter = new BinaryMessageFormatter(); 
    myImage = (MyImage)msg.Body; 
} 

coda deve essere creato prima dell'uso. Si può fare che quando l'applicazione viene avviata

hanno questo in classe:

private const string queueName = ".\\private$\\ImagesQueue"; 

e in applicazione di inizializzazione/startup assicurarsi di avere la coda:

if (!MessageQueue.Exists(queueName) 
{ 
    MessageQueue myQueue = MessageQueue.Create(queueName); 
} 

Con questo meccanismo della coda, Il motore non deve attendere il completamento del Viewer. Ciò migliorerebbe molto le prestazioni percepite perché è possibile generare l'immagine successiva (in realtà numero di esse) mentre quella precedente è ancora visualizzata. Non è così facile da ottenere con i file mappati in memoria.

MSMQ è un componente di Windows standard ma deve essere abilitato nelle funzionalità di Windows.

+0

Grazie. Mi piace l'accodamento Message Queue per quello che hai scritto: "Message Queue (MSMQ) secondo me è il più semplice da usare, ti dà il trasferimento dell'oggetto (al contrario dei flussi) e ti offre una persistenza di trasporto opzionale (utile nel caso il mittente o il destinatario non siano in esecuzione)." Grazie. – MTs

+0

Glad potrebbe aiutare. Ho ampliato la mia risposta con ulteriori dettagli su come creare la coda nell'avvio dell'app. –

11

Dal momento che .NET Framework 4.0 è possibile utilizzare i file di memoria mappati per questo, credo che sarebbe più veloce di un approccio basato su file system dal momento che non sono necessarie costose operazioni IO del file system.

Un file mappato in memoria contiene il contenuto di un file nella memoria virtuale . Questa mappatura tra un file e lo spazio di memoria abilita un'applicazione , compresi più processi, per modificare il file tramite leggendo e scrivendo direttamente nella memoria. I file mappati in memoria possono essere condivisi tra più processi. I processi possono mappare allo> stesso file mappato in memoria utilizzando un nome comune che viene assegnato dal processo che ha creato il file

Quindi, per condividere MMF attraverso più processi Hai solo bisogno di condividere un nome MMF, in modo da può prendere in considerazione seguente approccio:

  • Engine crea il file MMF e condividere con visualizzatore solo un nome (stringa)
  • View accesso MMF utilizzando MemoryMappedFile.OpenExisting(sharedName) metodo (vedi MSDN per un esempio accesso stesso MMF da diversi processi)

Link utili:

  • Memory-Mapped Files
  • Working with memory mapped files in .NET 4 - consiglio vivamente la lettura di questo articolo che descrive il motivo per cui MMF davvero "is the most efficient way for multiple processes on a single machine to communicate with each other". Fondamentalmente mostra che tutte le altre opzioni IPC sono basate su MMF.

(Dal menzionato sopra articolo) Se controlliamo altri metodi IPC possiamo vedere la seguente architettura: enter image description here

0

Sì, questo è un approccio valido. E supponendo che il tuo codice non contenga bug, sì è affidabile.

Ma è lento. Se il throughput è un problema, potrebbe essere necessario utilizzare Sockets (se si desidera dividere il motore e il visualizzatore su macchine diverse) o named pipe (per le comunicazioni tra processi sulla stessa macchina).

0

Utilizzare ZeroMQ. È molto facile da usare (più facile di WCF se si invia solo un tipo di messaggio), non ha un sovraccarico, e in generale una buona soluzione a molti problemi di comunicazione tra processi.

+0

Non penso che ZMQ sia un'ottima scelta in questo scenario - ZMQ è fantastico quando si inviano molti piccoli messaggi - e l'ordine di ricezione non deve essere garantito (o addirittura che essi arrivino a tutti) . Utile per qualcosa come un ticker di titoli aggiornato 60 volte al secondo. In questo caso, tuttavia, viene inviato un messaggio molto grande ogni 10-15 secondi: ZMQ non è l'ideale per questo caso d'uso. – MattDavey

+0

Sì, ma si inviano messaggi tra due componenti sullo stesso computer. Non si verificherà alcuna perdita di dati associata a UDP. – zmbq