subproceso que net hilos false ejemplo distinto desde delegados creó control checkforillegalcrossthreadcalls aquel winforms multithreading

que - En WinForms, ¿por qué no puedes actualizar los controles de UI desde otros hilos?



invoke en vb net (8)

Estoy seguro de que hay una buena (o al menos decente) razón para esto. ¿Qué es?


Hmm, no estoy muy seguro, pero creo que cuando tenemos controles de progreso como barras de espera, barras de progreso, podemos actualizar sus valores desde otro hilo y todo funciona bien sin problemas técnicos.


Creo que esta es una pregunta brillante, y creo que se necesita una mejor respuesta.

Sin duda, la única razón es que hay algo en un marco en algún lugar que no es muy seguro para subprocesos.

Ese "algo" es casi cada miembro de instancia en cada control en System.Windows.Forms.

La documentación de MSDN para muchos controles en System.Windows.Forms, si no todos, dice "Cualquier miembro público estático (compartido en Visual Basic) de este tipo es seguro para subprocesos. No se garantiza que ningún miembro de instancia sea seguro para subprocesos".

Esto significa que los miembros de instancia como TextBox.Text {get; set;} TextBox.Text {get; set;} no son reentrantes .

Hacer que cada uno de los miembros de la instancia sea seguro para las amenazas puede generar una sobrecarga que la mayoría de las aplicaciones no necesitan. En cambio, los diseñadores del framework .Net decidieron, y creo que correctamente, que la carga de sincronizar el acceso a los controles de formularios desde múltiples hilos debería ser puesta en el programador.

[Editar]

Aunque esta pregunta solo pregunta "por qué" aquí hay un enlace a un artículo que explica "cómo":

Cómo hacer llamadas Thread-Safe a controles de Windows Forms en MSDN

http://msdn.microsoft.com/en-us/library/ms171728.aspx


Aunque suena razonable, la respuesta de Johns no es correcta. De hecho, incluso cuando usas Invoke, todavía no estás seguro y no te encuentras en situaciones de bloqueo. Cuando se trata de eventos disparados en un hilo de fondo, usar Invoke puede incluso llevar a este problema.


La verdadera razón tiene más que ver con las condiciones de carrera y se remonta a la antigua Win32 veces. No puedo explicar los detalles aquí, las palabras clave son bombas de mensajes, eventos WM_PAINT y las diferencias sutiles entre "ENVIAR" y "POST".


Más información se puede encontrar aquí aquí y aquí .


Creo que esta es una pregunta brillante, y creo que se necesita una mejor respuesta.

Sin duda, la única razón es que hay algo en un marco en algún lugar que no es muy seguro para subprocesos. ¿Es un problema con .NET o Win32? ¿Y por qué no hay un empuje para arreglar la fuente en lugar de imponer lo que, para mí, parece una desagradable tarea?

¿Alguien sabe dónde está el verdadero problema subyacente?


De vuelta en 1.0 / 1.1 no se lanzó ninguna excepción durante la depuración, lo que obtuve en su lugar fue un escenario de ejecución intermitente en tiempo de ejecución. ¡Bonito! :) Por lo tanto, con 2.0 hicieron que este escenario arrojara una excepción y con razón.

La razón real de esto es probablemente (como dice Adam Haile) algún tipo de problema de concurrencia / locky. Tenga en cuenta que la API normal .NET (como TextBox.Text = "Hello";) envuelve los comandos ENVIAR (que requieren acción inmediata) que pueden crear problemas si se realizan en un hilo separado del que ejecuta la actualización. El uso de Invoke / BeginInvoke utiliza un POST que pone en cola la acción.

Más información sobre ENVIAR y POST aquí .


Es para que no tenga dos cosas tratando de actualizar el control al mismo tiempo. (Esto podría suceder si la CPU cambia al otro hilo en el medio de una escritura / lectura) La misma razón por la que necesita usar mutexes (o alguna otra sincronización) al acceder a variables compartidas entre múltiples hilos.

Editar:

En otros lenguajes, como C ++, puedes probar y hacer esto (sin excepción, como en WinForms), ¡pero acabarás aprendiendo por las malas!

Ahh sí ... cambio entre C / C ++ y C # y por lo tanto era un poco más genérico de lo que debería haber sido, lo siento ... Él está en lo correcto, puedes hacer esto en C / C ++, pero volverá a ¡morderte!


También sería necesario implementar la sincronización dentro de las funciones de actualización que son sensibles a ser llamadas simultáneamente. Hacer esto para los elementos de la interfaz de usuario sería costoso tanto para la aplicación como para el sistema operativo, y sería completamente redundante para la gran mayoría del código.

Algunas API proporcionan una forma de cambiar la propiedad actual del subproceso de un sistema para que pueda actualizar (o permanentemente) los sistemas de otros subprocesos sin necesidad de recurrir a la comunicación entre subprocesos.


Porque puede terminar fácilmente con un punto muerto (entre otros problemas).

Por ejemplo, el hilo secundario podría estar tratando de actualizar el control de la interfaz de usuario, pero el control de la interfaz de usuario estará esperando que se libere un recurso bloqueado por el hilo secundario, por lo que ambos hilos terminan esperando el uno al otro para terminar. Como otros han comentado, esta situación no es exclusiva del código de UI, pero es particularmente común.

En otros lenguajes, como C ++, puede probar y hacer esto (sin que se genere una excepción como en WinForms), pero su aplicación puede bloquearse y dejar de responder si se produce un interbloqueo.

Por cierto, puede decirle fácilmente a la cadena de interfaz de usuario que desea actualizar un control, simplemente cree un delegado, luego llame al método BeginInvoke (asincrónico) en ese control y transfiéralo a su delegado. P.ej

myControl.BeginInvoke(myControl.UpdateFunction);

Esto es el equivalente a hacer un PostMessage de C ++ / MFC a partir de un hilo de trabajo