Uso de la aplicación.DoEvents()

Uso de la aplicación.DoEvents()

Hmya, la mística perdurable de DoEvents(). Ha habido una enorme cantidad de reacciones en su contra, pero nadie explica realmente por qué es "malo". El mismo tipo de sabiduría que "no mutes una estructura". Erm, ¿por qué el tiempo de ejecución y el lenguaje admiten la mutación de una estructura si eso es tan malo? La misma razón:te pegas un tiro en el pie si no lo haces bien. Fácilmente. Y hacerlo bien requiere saber exactamente lo que hace, que en el caso de DoEvents() definitivamente no es fácil de asimilar.

De inmediato:casi cualquier programa de Windows Forms en realidad contiene una llamada a DoEvents(). Está ingeniosamente disfrazado, sin embargo, con un nombre diferente:ShowDialog(). Es DoEvents() que permite que un diálogo sea modal sin congelar el resto de las ventanas de la aplicación.

La mayoría de los programadores quieren usar DoEvents para evitar que su interfaz de usuario se congele cuando escriben su propio ciclo modal. Ciertamente hace eso; envía mensajes de Windows y recibe cualquier solicitud de pintura. Sin embargo, el problema es que no es selectivo. No solo envía mensajes de pintura, también entrega todo lo demás.

Y hay un conjunto de notificaciones que causan problemas. Vienen desde aproximadamente 3 pies en frente del monitor. El usuario podría, por ejemplo, cerrar la ventana principal mientras se ejecuta el bucle que llama a DoEvents(). Eso funciona, la interfaz de usuario se ha ido. Pero su código no se detuvo, todavía está ejecutando el ciclo. Eso es malo. Muy, muy mal.

Hay más:el usuario puede hacer clic en el mismo elemento de menú o botón que hace que comience el mismo ciclo. Ahora tiene dos bucles anidados que ejecutan DoEvents(), el bucle anterior se suspende y el nuevo bucle comienza desde cero. Eso podría funcionar, pero vaya, las probabilidades son escasas. Especialmente cuando termina el bucle anidado y se reanuda el suspendido, tratando de terminar un trabajo que ya estaba terminado. Si eso no funciona con una excepción, entonces seguramente los datos están codificados al infierno.

Volver a ShowDialog(). Ejecuta DoEvents(), pero tenga en cuenta que hace algo más. Deshabilita todas las ventanas de la aplicación , aparte del diálogo. Ahora que el problema de los 3 pies está resuelto, el usuario no puede hacer nada para estropear la lógica. Se resuelven los modos de falla de cerrar la ventana y comenzar el trabajo nuevamente. O para decirlo de otra manera, no hay forma de que el usuario haga que su programa ejecute el código en un orden diferente. Se ejecutará de manera predecible, tal como lo hizo cuando probó su código. Hace que los diálogos sean extremadamente molestos; ¿Quién no odia tener un diálogo activo y no poder copiar y pegar algo desde otra ventana? Pero ese es el precio.

Que es lo que se necesita para usar DoEvents de forma segura en su código. Establecer la propiedad Enabled de todos sus formularios en falso es una forma rápida y eficiente de evitar problemas. Por supuesto, a ningún programador le gusta hacer esto. Y no lo hace. Por eso no deberías usar DoEvents(). Deberías usar hilos. A pesar de que te entregan un arsenal completo de formas de disparar tu pie de formas coloridas e inescrutables. Pero con la ventaja de que solo disparas tu propio pie; (típicamente) no permitirá que el usuario dispare la suya.

Las próximas versiones de C# y VB.NET proporcionarán un arma diferente con las nuevas palabras clave await y async. Inspirado en pequeña parte por los problemas causados ​​por DoEvents y subprocesos, pero en gran parte por el diseño de la API de WinRT que requiere que mantenga su interfaz de usuario actualizada mientras se lleva a cabo una operación asíncrona. Como leer de un archivo.


Puede ser, pero es un truco.

Consulte ¿Es DoEvents malvado? .

Directo desde la página de MSDN a la que el desarrollador hizo referencia:

Microsoft advierte contra su uso.

Además, lo considero un truco porque su comportamiento es impredecible y propenso a los efectos secundarios (esto proviene de la experiencia al tratar de usar DoEvents en lugar de crear un nuevo hilo o usar un trabajador en segundo plano).

No hay machismo aquí:si funcionara como una solución sólida, estaría en todo. Sin embargo, tratar de usar DoEvents en .NET no me ha causado más que dolor.


Sí, hay un método DoEvents estático en la clase de aplicación en el espacio de nombres System.Windows.Forms. System.Windows.Forms.Application.DoEvents() se puede usar para procesar los mensajes que esperan en la cola en el subproceso de la interfaz de usuario cuando se realiza una tarea de ejecución prolongada en el subproceso de la interfaz de usuario. Esto tiene la ventaja de hacer que la interfaz de usuario parezca más receptiva y no "bloqueada" mientras se ejecuta una tarea larga. Sin embargo, casi siempre NO es la mejor manera de hacer las cosas. Según Microsoft, llamar a DoEvents "... hace que el hilo actual se suspenda mientras se procesan todos los mensajes de la ventana de espera". Si se desencadena un evento, existe la posibilidad de errores inesperados e intermitentes que son difíciles de rastrear. Si tiene una tarea extensa, es mucho mejor hacerlo en un hilo separado. La ejecución de tareas largas en un subproceso separado permite que se procesen sin interferir con el funcionamiento continuo de la interfaz de usuario. Mira aquí para más detalles.

Aquí hay un ejemplo de cómo usar DoEvents; tenga en cuenta que Microsoft también proporciona una advertencia contra su uso.