texto tabla sirve que proteger power posicion para marcadores hacer formularios formulario controles contenido como agregar actualizar c# logging textbox real-time appendtext

c# - tabla - Cuadro de texto Agregar texto rápido a texto



para que sirve agregar texto en word (6)

Tengo un hilo de BackgroundWorker que está publicando mensajes, usando BeginInvoke en un cuadro de texto en la GUI. El método, write_debug_text , que muestra texto en el cuadro de texto usa AppendText y también escribe el texto en la Console .

La apariencia es que BackgroundWorker está escribiendo demasiado rápido para que write_debug_text mantenga al día. Establecí un punto de interrupción en write_debug_text y tuve que esperar mucho antes de que se golpeara. Muchas llamadas a ''BeginInvoke'' ocurren antes de que se golpee el punto de interrupción.

Estoy buscando una pantalla de mensajes en tiempo real en la interfaz de usuario, al igual que System.Console en VS C # Express IDE.

Desde la búsqueda en SO, entiendo que AppendText es el método más rápido de usar y que las cadenas pueden tener que ser reasignadas.

Algunas respuestas sugieren usar StringBuilder luego escribir ese texto periódicamente en el cuadro de texto. Pero esto requiere agregar más eventos y temporizadores; que preferiría no hacer (mi aplicación simple se vuelve cada vez más compleja).

¿Cómo puedo escribir en tiempo real en el cuadro de texto (y hacer que se visualice)?

Mi idea actual es crear un widget heredando de Textbox que usa una cola de texto y un temporizador.

Edición 1: código de muestra

Aquí hay un fragmento de mi código:

private m_textbox; //... m_textbox.BeginInvoke(new write_debug_text_callback(this.write_debug_text), new object[] { debug_text }); return; private void write_debug_text(string text) { string time_stamp_text = ""; time_stamp_text = DateTime.Now.ToString() + " "; time_stamp_text += text; m_textbox.AppendText(time_stamp_text); m_textbox.Update(); System.Console.Write(time_stamp_text); return; }

Intenté cambiar BeginInvoke a Invoke y mi aplicación se colgó. Cuando hago una pausa / corte utilizando el depurador, el puntero de ejecución está en la llamada a Invoke .

Por cierto, tengo muchos años de experiencia con Java, C ++ y C. Estoy en mi quinto mes con C #.


No use BeginInvoke . Use Invoke lugar. Ver aplicación no responde mientras se agregan miles de filas . Ese no es exactamente el mismo problema (está usando un DataGridView en lugar de un cuadro de texto), pero es el mismo tipo de cosas. Su BackgroundWorker está comenzando un montón de tareas asincrónicas. Será mejor que hagas uno a la vez.


Podría intentar usar un control RichTextBox y evitar que refresque su UI, excepto cada cierto tiempo. Algo así como la sugerencia de StringBuilder , pero un poco más simple. Vea esta pregunta SO para un ejemplo de cómo hacer eso,


Si desea escribir en tiempo real dentro del cuadro de texto, ¿por qué no utiliza la BeginInvoke sincrónica en lugar de BeginInvoke que BeginInvoke cola la función para que se llame más tarde?


Si hay una gran cantidad de mensajes que se muestran, entonces es probable que el problema sea problemas de asignación de memoria.

Supongamos que cada mensaje tiene 30 caracteres. Esto sería (aproximadamente) 60 bytes. Supongamos además que está agregando 10 mensajes por segundo. Luego, en el primer segundo las cadenas generadas serán: 60 + 120 + 60 + 180 + 60 + 240 + 60 + 300 + ... + 60 + 600 = 3840 bytes. En el segundo segundo, el total asciende a 13,740 bytes. En el tercer segundo: 29,640. 4º: 51,540. ... 10º: 308,940 bytes.

Después de 18 segundos, se alcanza un megabyte y las cadenas mostradas son de 11 kb cada una.

En la marca de un minuto estamos en 10 Mb de cadena asignada. En dos minutos, 43 Mb están dedicados a estos mensajes, y los tamaños de cadena aumentan a 71 kb cada uno. Después de tres minutos, los mensajes tienen más de 100 kb de tamaño y casi 100 Mb están dedicados a ellos.

¡Esta es la razón por la cual StringBuilder es tan importante para construir cadenas largas!

Pero dado que su plan es mostrar cada paso intermedio, StringBuilder no lo ayudará aquí. Esta GUI requiere que genere una carga métrica de cadenas.

Una posible solución a este problema es cortar el frente de las cuerdas mientras está insertando datos en la parte posterior. Seguirá asignando mucha memoria a las cadenas, pero las cadenas individuales tendrán un tamaño limitado y, por lo tanto, será mucho más fácil para el tiempo de ejecución encontrar un lugar para ellas en la memoria, y la tasa de asignación ir hacia abajo también.

Esto debería reducir su presión de recolección de basura:

private const int maxDisplayTextLength = 5000; private void write_debug_text(string text) { string time_stamp_text = ""; time_stamp_text = DateTime.Now.ToString() + " " + text; string previous = m_textbox.Text; if (previous.Length + time_stamp_text.Length > maxDisplayTextLength) m_textbox.Text = previous.Substring(0, maxDisplayTextLength - time_stamp_text.Length) + time_stamp_text; else m_textbox.Text = previous + time_stamp_text; m_textbox.Update(); System.Console.Write(time_stamp_text); return; }



Utilicé el consejo de @Jeffre L. Whitledge y reduje el número de asignaciones de cadenas. Como esta es una aplicación cerrada con un número fijo de cadenas, guardé en caché las cadenas. Esto produjo un efecto secundario de que mi programa se ejecutara significativamente más rápido.

Uno de mis problemas sigue siendo la lentitud en la respuesta de Windows a los mensajes. Esto se puede ver cuando se actualiza la barra de progreso. Existe un retraso definido desde el momento en que se envía un mensaje (como agregar texto) hasta el momento en que se realiza.