2010-07-29 22 views
10

Ricevo circa 5 messaggi al secondo. Ognuno di loro ha una stringa, che ho concateno a una stringa principale che contiene tutti i messaggi ricevutiStringBuilder o + =

string _masterText = ""; 
    public void AddNewMessage(string text) // this is going to be call at least 5 times/second 
    { 
     _masterText += text;  
    } 

E 'questo il modo in cui gli appropriati per farlo? o dovrei usare al posto StringBuilder, come:

StringBuilder _masterText = new StringBuilder(); 
    public void AddNewMessage(string text) // this is going to be call at least 5 times/second 
    { 
     _masterText.Append(text); 
    } 

Grazie

+0

Penso che la risposta dipenda da cosa intendi fare con questo _masteresto finale successivo. –

+0

Lo mostrerò in un memoEdit (DevExpress) nella GUI – pedroruiz

risposta

15

StringBuilder è generalmente considerato l'opzione migliore, ma in questo caso non utilizzerei né lo .

Anche con StringBuilder, a quel ritmo il buffer di caratteri sottostante sarà presto abbastanza grande da rimanere bloccato sull'Heap di oggetti di grandi dimensioni. Ciò causerà problemi per la salute di un'applicazione che deve rimanere in esecuzione per un po '.

Invece, utilizzerei uno System.Collections.Generic.List<string> e chiamo semplicemente il metodo .Add() per ogni nuovo messaggio. A seconda di cosa fai con questi messaggi potresti anche trovare che un altro tipo di raccolta è più appropriato (forse un Queue<string>), ma questa è la direzione che dovresti seguire. Utilizzando una raccolta, la memoria utilizzata da ogni singola stringa non verrà conteggiata per le dimensioni dell'oggetto di raccolta. Invece, ogni stringa aggiungerà solo pochi byte per il riferimento. Ci vorrà molto più tempo per incorrere in problemi con la compattazione del Large Object Heap.

Se si verificano ancora problemi dopo il passaggio a una raccolta, è possibile utilizzare uno stream e scrivere le stringhe sul disco. In questo modo, non hai più di una stringa nella RAM alla volta. Ora, l'unico modo in cui hai problemi è se le singole stringhe sono 85000 byte o più grandi.

+0

Sarebbe anche una buona idea scaricare i messaggi su disco ogni ora o così per mantenere l'utilizzo della memoria a un livello ragionevole. A seconda dell'importanza di questi messaggi, potresti voler avere un thread dedicato per gestire la memorizzazione dei messaggi. – ChaosPandion

+0

questo non verrà eseguito durante tutto il giorno, l'utente avvierà l'applicazione e sarà in esecuzione per 5 minuti al massimo – pedroruiz

+0

@pedroruiz ok, va bene. Elenco e coda sono ancora più facili e veloci e rappresentano ancora il modo corretto di gestirli. –

3

Ogni 200 ms è neanche un sondaggio molto faticoso, a prescindere StringBuilder è sempre meglio.

0

StringBuilder è il tuo amico!

8

Ricordare che la classe String è immutabile. Non è possibile cambiare una stringa. Quando si "concatenano" le stringhe, si sta veramente creando una nuova stringa e copiando il contenuto della stringa originale su di essa, quindi aggiungendo il contenuto della nuova stringa.

Inizia a utilizzare la memoria molto rapidamente se si aggiungono stringhe di grandi dimensioni.

+0

Specialmente una volta ogni stringa intermedia occupa 80.000 byte e passa direttamente al LOH. –

1

Se sei pronto per una lettura, penso che la discussione su http://dotnetperls.com/stringbuilder-1 sia davvero utile. Controlla i link alle metriche reali su velocità e utilizzo della memoria.

Inoltre, controlla la discussione di Joel Spolsky su "Shlemeil the Painter's Algorithm". Sebbene stia parlando della funzione strcat di C, il principio si applica all'operatore più C# sulle stringhe. Inoltre, è buono per una risata.

In generale, si consiglia StringBuilder se si sta eseguendo l'operazione di accodamento rapidamente o con molte stringhe di grandi dimensioni.

0

Dipende anche dallo scenario. Senza dubbio è più veloce aggiungerlo con l'elenco generico come confronto all'oggetto stringbuilder. Ma durante il tempo di recupero dei dati dall'elenco generico, sarà molto più lento rispetto all'oggetto stringbuilder.

Il costruttore di stringhe tornerà rapidamente utilizzando _masterText.ToString() ma con la lista generica, potresti dover tirare il valore usando l'iterazione. E che sarà processo costoso come ad esempio: -

for (int x = 0; x < 100; x++) 
    { 
     Label3.Text += gen_list[x]; 
    } 

Oppure si può provare con

Label3.Text = string.join ("", gen_list.ToArray());

quindi l'operazione di recupero sarà più lenta e costosa e si noterà facilmente il picco della CPU.