2010-10-12 2 views
8

Stiamo sviluppando un'applicazione che legge continuamente i dati da un numero di dispositivi hardware esterni. La velocità dati è compresa tra 0,5 MB - 10 MB/sec, a seconda della configurazione hardware esterna.Registrazione/registrazione rapida dei dati su una filettatura separata in C#

La lettura dei dispositivi esterni viene attualmente eseguita su un BackgroundWorker. Cercare di scrivere i dati acquisiti su disco con questo stesso BackgroundWorker non sembra essere una buona soluzione, quindi quello che vogliamo fare è, accodare questi dati per essere scritti su un file, e fare in modo che un altro thread rimuova i dati e scriva un file. Si noti che ci sarà un singolo produttore e un singolo consumatore per i dati.

Stiamo pensando di utilizzare una coda sincronizzata per questo scopo. Ma pensavamo che questa ruota fosse stata inventata così tante volte, quindi dovremmo chiedere alla comunità SO di dare qualche input.

Qualsiasi suggerimento o commento su cose che dovremmo fare attenzione sarebbe apprezzato.

risposta

2

Sono abbastanza sicuro che la coda sarà più o meno ok. Ma assicurati di utilizzare un metodo efficiente per archiviare/recuperare i dati, non per revisionare la procedura di registrazione con allocazione/deallocazione di memoria. Vorrei andare per un buffer di memoria pre-allocato, e usarlo come una coda circolare.

+0

Daniel, pensi che possiamo usare le code .NET per questo scopo? Stiamo pensando di utilizzare ConcurrentQueue per archiviare i puntatori ai dati, ma pre-allocare la memoria per i dati prima di iniziare la registrazione. – SomethingBetter

+0

Che tipo di dati registrate? Strutturazioni, semplici byte, infatti, la mia domanda è che se i dati possono essere serializzati facilmente in pacchetto e letti in sequenza. Sei di basso livello qui, rimani di basso livello. –

-1

Hai provato MSMQ

+0

Immagino che MSMQ non sia d'aiuto, dato che abbiamo così tanti dati e MSMQ è in qualche modo API di alto livello che consuma CPU anche quando fa pochissimo. –

2

Potresti aver bisogno di un telefono

es. Codice

protected Queue<Byte[]> myQ; 
or 
protected Queue<Stream> myQ; 

//when u got the content try 
myQ.Enque(...); 

e utilizzare un altro thread per estrarre la coda di

// another thread 
protected void Loging(){ 
while(true){ 
    while(myQ.Count > 0){ 
    var content = myQ.Dequeue(); 
    // save content 
    } 
    System.Threading.Thread.Sleep(1000); 
} 
} 
+0

Beh, in questo caso dovremmo implementare noi stessi i meccanismi di blocco. Il codice sopra non sembra essere thread-safe. – SomethingBetter

+0

.NET 4.0 ha un ConcurrentQueue, che è thread-safe – SomethingBetter

+0

quando si usa Queue, non ci si deve preoccupare del thread safe. quando vuoi ottenere un elemento in coda, ti basta disconnettere. e non ci sarà alcun cross thread che elabora lo stesso oggetto – Bonshington

3

avrei fatto quello che una combinazione di ciò che fa mr 888.

In basic in avete 2 operatori in background, uno che legge dal dispositivo hardware. uno che scrive i dati sul disco.

Hardware sfondo lavoratore:
Aggiunge mandrini sui dati dall'hardware nel Queue<>. In qualsiasi formato avete in.

Scrivi sfondo lavoratore
analizza i dati, se necessario, e discariche su disco.

Una cosa da considerare qui è ottenere i dati dall'hardware al disco il più rapidamente possibile?
Se sì, il test di brackground di scrittura dovrebbe essere eseguito in modo semplice in un ciclo con una sospensione di 100 ms o 10 ms nel ciclo while per verificare se la coda contiene dati.
Se la risposta è No, allora vorrei che dormisse una quantità similare (Prendendo l'ipotesi che la velocità che si ottiene dall'hardware cambi periodicamente) e faccia solo scrivere sul disco quando ha circa 50-60mb di dati. Prenderò in considerazione la possibilità di farlo in questo modo perché i dischi rigidi moderni possono scrivere circa 60mb di secondo (questo è un disco fisso del desktop, il tuo enterprice potrebbe essere molto più veloce) e scrivere costantemente i dati in piccoli mandrini è uno spreco di banda I/O.

+0

Grazie per l'idea. Sì, penso che dovremmo bufferizzare i dati e scriverli in grandi blocchi. – SomethingBetter

0

Ho una situazione simile, nel mio caso ho utilizzato una coda asincrona lockfree con un oggetto sincrono LIFO Fondamentalmente i thread che scrivono in coda impostano l'oggetto sync in LIFO mentre gli altri thread 'worker' ripristinano la sincronizzazione oggetto in LIFO Abbiamo fissato un numero di oggetti di sincronizzazione uguali ai thread. il motivo dell'utilizzo di un LIFO è quello di mantenere il numero minimo di thread in esecuzione e un uso migliore del sistema di cache.