2009-10-26 10 views
5

Estoy realmente avergonzado de hacer una pregunta tan trivial pero depurar algún software ahora me convenció de que realmente no entiendo este problema:Asincronía y eventos .NET?

¿Cómo funcionan los eventos .NET vistos desde una altitud de 20,000 pies? No me refiero al patrón de delegado/controlador de eventos y todo esto. Lo que quiero decir es: ¿cuál es la GRAN imagen:

  1. El código A está haciendo algo.
  2. Se produce algún disparo externo. Digamos, por ejemplo, que el usuario hizo clic en algún control.
  3. Ocurre una magia y se llama al controlador de eventos para el evento.
  4. sucede otra magia después de que el manejador de eventos regrese.

Ahora, ¿cuál es la magia? ¿Cómo se relaciona esto con los hilos? ¿El subproceso que ejecuta mi código se interrumpe cuando se produce el evento y luego se reanuda después de que el controlador de eventos devuelve? Pero busqué en Google y found out que los controladores .NET se llaman sincrónicamente en el hilo original. Entonces, ¿quién se ocupa de detener y reanudar el Código A? ¿Qué ocurre si los eventos están anidados (es decir, el Evento 2 ocurre cuando se está ejecutando el controlador de eventos para el Evento 1)?

Editar: Por lo que yo entiendo las respuestas dicen que el lanzador de eventos para el próximo evento se ejecutará sólo después de que el controlador de eventos actualmente en ejecución finaliza. Esto significa que su código no se interrumpe: la línea n siempre se ejecutará inmediatamente después de la línea n-1 y justo antes de la línea n + 1. Sin embargo, justo antes de publicar la pregunta, estaba depurando un programa que controlaba, a través de la automatización, Internet Explorer (usando SWExplorerAutomation de Webius). Estoy bastante seguro de que mientras estaba avanzando paso a paso por el código fui "secuestrado" :-) a algún controlador de eventos y volví a la posición interrumpida en el código una vez que ese controlador de eventos finalizó su tarea. Esto significa que o no comprende las respuestas, o que el programa se comporta de manera diferente mientras pasa por el depurador.

Respuesta

3

Déjeme aclarar su problema. La magia es el bucle de mensajes de Windows. Verá en su ejemplo, en realidad, no hay nada que haga que el Código A se detenga cuando ocurra un evento. Por el contrario, esta es la secuencia.

Cuando se ejecuta el código A, el usuario hace clic en un botón. El mensaje de la ventana del botón se pone en cola, pero no pasa nada. Cuando el código A sale de su función o abandona el control nuevamente al bucle de mensajes, se procesa el evento Click y se ejecuta el controlador de eventos.

Pruebe este experimento. Coloque un bucle infinito dentro de su programa en el hilo principal y luego haga clic en la interfaz de usuario. Notará que la interfaz de usuario no responderá y no se ejecutarán los controladores de eventos.

+0

Esto es cierto para las aplicaciones de WinForms, pero no olvide el caso más general, donde no está involucrado el bombeo de mensajes. En este caso, todo se ejecuta sincrónicamente sin un mitigator, y no hay magia involucrada. – bzlm

+0

@bzim Entiendo los buenos viejos mulit-mailboxes, wake-me-up-when-a-message-llega-si-estoy-con-una-mayor-prioridad-que-la-actual-ejecución-modelo de la tarea como en el buen viejo RMX de Intel. Lo que no entiendo es el truco de mano de Windows. – Avi

2

Lo que verá de 20.000 pies es el MessageLoop. Está dentro de Application.Run().

En pocas palabras, este es un tiempo de ciclo que recorre toda la vida útil de su aplicación y hace

// pseudo code, I did not reflector Application.Run 
    while (GetMessage(ref msg) 
    { 
    DispatchMessage(ref msg); 
    } 

Usted notará el simgle hilos cuando se toma demasiado tiempo evento de manipulación 1, su aplicación se etiquetado como "no responde" en el Administrador de Tareas.

Un método relacionado es Application.DoEvents(), pero aléjese de eso.

+0

Esto es cierto para las aplicaciones de WinForms, pero no olvide el caso más general, donde no está involucrada la bomba de mensajes. En este caso, todo se ejecuta sincrónicamente sin un mitigator, y no hay magia involucrada. – bzlm

+0

bzim, reaccioné al ejemplo de Control-clic. Tienes razón en general, pero creo que OP está pensando en WinForms. –

1

Los eventos son punteros a funciones (como solíamos tener en C++). Cuando utilizas el evento plain vanilla .NET, en realidad estás llamando a las funciones que están conectadas usando + = a ese evento. Entonces, desde 20,000 pies, su código realmente llama a algún otro código igual que a llamar a otra función. Es por eso que se llama sincrónicamente y en el mismo hilo.

Cuando estamos dentro del control WinForms/WPF también tenemos un bucle de mensaje a tener en cuenta: Todos los eventos que ocurren dentro del contexto del formulario agregan un mensaje al bucle de mensaje en lugar de llamar directamente a un método.

El hilo principal de las encuestas de control que repiten los nuevos mensajes y cuando aparece un nuevo mensaje lo ejecuta (nuevamente en el hilo principal) pero ahora no es exactamente sincrónico.

Esta es la razón por la que si un formulario está ocupado haciendo algo y se presiona un botón, se tarda un poco antes de presionar ese botón. esta es también la razón por la que si invalida un control, su apariencia solo cambiará después de que salga del método en ejecución (y se procese el siguiente mensaje).

+0

0. Gracias por su respuesta :-) 1. ¿Está diciendo que CADA control (botón, etiqueta, cuadro de lista, etc.) en un formulario tiene su propio bucle de mensaje y su propio hilo? Y cada control HTML dentro de una página web? Esto parece realmente un desperdicio. 2. No entendí toda la sección que comienza con "Esta es la razón ...". ¿Podrías explicar? – Avi

+0

1. Si recuerdo correctamente Cada ventana principal tiene su propio bucle de mensajes, no cada control 2. El bucle de mensajes es el motivo por el que las llamadas en el mismo hilo no son síncronas, es decir, al presionar un botón no se produce disparar de manera intermedia, pero se ejecuta en el contexto del hilo principal. –

+0

Dror, no todas las ventanas, todas las aplicaciones. Y mientras puedes comenzar un segundo que es muy raro. –

Cuestiones relacionadas