2010-07-29 12 views
10

Recibo alrededor de 5 mensajes por segundo. Cada uno de ellos tiene una cadena, que me concatenar una cadena principal que contiene todos los mensajes recibidosStringBuilder o + =

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

Es esta la forma apropió de hacerlo? o debería usar en su lugar StringBuilder, como:

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

Gracias

+0

Creo que la respuesta depende de lo que pretendas hacer con este _maseterText resultante a continuación. –

+0

Lo mostraré en un memoEdit (DevExpress) en la GUI – pedroruiz

Respuesta

15

StringBuilder generalmente se considera la mejor opción, pero en este caso yo tampoco usaría .

Incluso con StringBuilder, a esa velocidad el búfer de caracteres subyacente pronto será lo suficientemente grande como para quedar atascado en el Gran montón de objetos. Esto causará problemas para la salud de una aplicación que necesita seguir funcionando por un tiempo.

En su lugar, utilizaría un System.Collections.Generic.List<string> y simplemente llame al método .Add() para cada nuevo mensaje. Dependiendo de lo que haga con estos mensajes, también puede encontrar otro tipo de colección más apropiado (quizás un Queue<string>), pero esta es la dirección que debe seguir. Al usar una colección, la memoria utilizada por cada cadena individual no contará para el tamaño del objeto de colección. En cambio, cada cadena solo agregará algunos bytes para la referencia. Esto llevará mucho más tiempo para tener problemas al compactar el Gran montón de objetos.

Si aún tiene problemas después de cambiar a una colección, puede usar una secuencia y escribir las cadenas en el disco. De esta forma, nunca tendrás más de una cadena en RAM a la vez. Ahora, la única forma en que tiene problemas es si las cadenas individuales tienen 85000 bytes o más.

+0

También sería una buena idea descargar los mensajes en el disco cada hora más o menos para mantener el uso de la memoria a un nivel razonable. Según la importancia de estos mensajes, es posible que desee tener un hilo dedicado que administre el almacenamiento de los mensajes. – ChaosPandion

+0

esto no se ejecutará durante todo el día, el usuario iniciará la aplicación y se ejecutará durante 5 minutos como máximo – pedroruiz

+0

@pedroruiz bien, está bien. List y Queue son aún más fáciles y rápidas, y siguen siendo la forma correcta de manejar esto. –

3

cada 200 ms tampoco un sondeo muy exigente, independientemente StringBuilder es siempre mejor.

0

¡StringBuilder es tu amigo!

8

Recuerde que la clase String es inmutable. No es posible cambiar una cadena. Cuando está "concatenando" cadenas, realmente está creando una nueva cadena y copiando el contenido de la cadena original, y luego agregando el contenido de la nueva cadena.

Esto comienza a usar la memoria muy rápidamente si está agregando cadenas grandes.

+0

Especialmente una vez que cada cadena intermedia ocupa 80,000 bytes y va directamente al LOH. –

1

Si está listo para leer, creo que la discusión en http://dotnetperls.com/stringbuilder-1 es realmente útil. Consulte los enlaces a métricas reales sobre la velocidad y el uso de la memoria.

Además, consulte la discusión de Joel Spolsky sobre "Shlemeil the Painter's Algorithm". Aunque está hablando de la función strcat de C, el principio se aplica al operador C plus en las cadenas. Además, es bueno para una risa.

En general, recomiendo StringBuilder si está realizando la operación de agregar rápidamente o con muchas cadenas grandes.

0

Depende del escenario también. Sin duda, es más rápido agregarlo con la lista genérica en comparación con el objeto del generador de cadenas. Pero durante el tiempo de recuperación de datos de la lista genérica, será mucho más lento en comparación con el objeto del generador de cadenas.

El generador de cadenas volverá rápidamente utilizando _masterText.ToString() pero con la lista genérica, es posible que deba extraer el valor con la iteración. Y que será costoso proceso, tales como: -

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

O puede probar con

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

entonces la operación de recuperación será más lenta y costosa, y se puede notar que la CPU se dispara fácilmente.