c# multithreading invoke dispatcher begininvoke

c# - Dispatcher Invoke(…) vs BeginInvoke(…) confusión



multithreading (1)

Cuando usa Dispatcher.BeginInvoke significa que programa la acción dada para su ejecución en el subproceso de la interfaz de usuario en un momento posterior, y luego retorna el control para permitir que el subproceso actual continúe ejecutándose. Invoke bloquea a la persona que llama hasta que finaliza la acción programada.

Cuando use BeginInvoke su bucle se ejecutará súper rápido ya que BeginInvoke regresa de inmediato. Esto significa que está agregando muchas y muchas acciones a la cola de mensajes. Los estás agregando mucho más rápido de lo que realmente pueden procesarse. Esto significa que hay mucho tiempo entre cuando se programa un mensaje y cuando realmente se puede ejecutar.

La acción real que está ejecutando utiliza el campo _number . Pero _number está siendo modificado por el otro hilo muy rápidamente y mientras la acción está en la cola . Esto significa que no mostrará el valor de _number en el momento en que programó la acción, sino más bien qué es después de que haya continuado en su ciclo muy cerrado.

Si utiliza Dispatcher.Invoke cambio, evita que el bucle se "adelante" y que tenga múltiples eventos programados, lo que garantiza que el valor que está escribiendo sea siempre el valor "actual". Además, al forzar cada iteración del bucle a esperar a que se ejecute el mensaje, hace que el bucle sea mucho menos "ajustado", por lo que no puede ejecutarse tan rápidamente en general.

Si desea utilizar BeginInvoke lo primero que realmente necesita hacer es ralentizar su ciclo. Si desea que actualice el texto cada segundo, o cada 10 ms, o lo que sea, puede usar Thread.Sleep para esperar el tiempo adecuado.

A continuación, debe tomar una copia de _number antes de pasarla al Dispatcher para que muestre el valor en el momento en que lo programó, no en el momento en que se ejecuta:

while (true) { if (_number++ > 10000) _number = 0; int copy = _number; this.Dispatcher.BeginInvoke(new Action(() => UpdateText(copy)) , System.Windows.Threading.DispatcherPriority.Background, null); Thread.Sleep(200); }

private void UpdateText(int number) { this.Text = number.ToString(); }

Estoy confundido por qué no puedo hacer que esta aplicación de contador de prueba funcione con 2 (o más) cuadros de contratexto que se ejecutan simultáneamente con el uso de "BeginInvoke" en mi Dispatcher en el método Count ().

Puede resolver el problema sustituyendo el BeginInvoke por un Invoke. Pero esto no resuelve mi confusión.

Aquí está el código de ejemplo del que estoy hablando:

public class CounterTextBox : TextBox { private int _number; public void Start() { (new Action(Count)).BeginInvoke(null, null); } private void Count() { while (true) { if (_number++ > 10000) _number = 0; this.Dispatcher.BeginInvoke(new Action(UpdateText), System.Windows.Threading.DispatcherPriority.Background, null); } } private void UpdateText() { this.Text = "" + _number; } }