No es una tarea trivial obtener un hilo para iniciar la ejecución del código en otro hilo. La clave del problema es que no se puede simplemente decir cualquier hilo para comenzar a ejecutar un método después de que ese hilo ya haya comenzado. El hilo de destino debe configurarse específicamente para recibir este tipo de solicitudes con anticipación.
El patrón habitual utilizado es el productor-consumidor. El hilo de destino girará alrededor de un bucle infinito esperando que los mensajes aparezcan en una cola de bloqueo. La cola está diseñada para bloquear hasta que aparezca un elemento en la cola, lo que evita que el hilo de destino consuma tiempo de CPU innecesariamente. Aquí hay una manera muy simple de obtener un hilo para aceptar la inyección de un delegado para su ejecución.
public class Example
{
private BlockingCollection<Action> queue = new BlockingCollection<Action>();
public Example()
{
new Thread(
() =>
{
while (true)
{
Action action = queue.Take();
action();
}
}).Start();
}
public void ExecuteAsync(Action action)
{
queue.Add(action);
}
}
Ahora, en el caso de una interfaz de usuario hilo que ya tiene un bucle de mensaje se ejecuta por lo que la clase Dispatcher
puede simplemente enviar un mensaje especial para la cola de mensajes que contiene el delegado para ser ejecutado. En el medio de procesar toda la pintura, los clics de los botones, etc., este mensaje especial también será recogido por el subproceso de la interfaz de usuario y comenzará a ejecutarse el delegado.
Entonces, ¿cómo funciona realmente la clase Dispatcher? Soy consciente de eso, , su trabajo principal es poner en cola acciones en un hilo específico, pero ¿cómo "envía" esas acciones al hilo ?
Al poner en cola a un delegado en una cola que supervisa el subproceso de destino.
¿Y cómo el hilo "obtiene" estas acciones?
Ejecutando un bucle infinito que supervisa la cola. La cola suele ser un tipo especial llamado cola de bloqueo que bloquea el hilo consumidor si la cola está vacía.
Mi mejor versión es que hay algún tipo de "lista de hilos" para cada hilo , pero de nuevo no tengo ni idea.
Pretty close. Excepto que los hilos no tienen una cola incorporada para este propósito. Tiene que ser configurado manualmente. Es por eso que solo los hilos diseñados específicamente pueden aceptar inyecciones de delegado. Los subprocesos de interfaz de usuario se configuran de esta manera porque Application.Run
crea el bucle de mensaje. En mi ejemplo, verá que tuve que usar BlockingCollection
y un bucle infinito para que funcione en un hilo de trabajo.
¿Está preguntando en el contexto de WPF o Silverlight? –
@JoeWhite, Ninguno. También puedes usar el 'Dispatcher' en una aplicación que no es gui. – ebb
@ebb, puedes usarlo en una aplicación sin GUI, pero realmente no tiene sentido ... hay herramientas más adecuadas para hacerlo. El despachador * está * diseñado teniendo en cuenta los escenarios de IU. –