without understanding method ejemplos create await async c# asynchronous async-await

c# - understanding - Actualización de la interfaz de usuario de eventos usando asyc a la espera



task void c# (4)

// Solo declara un delegado asi

delegate void Add(string msg);

// Luego declara el método de delegado así:

var add = new Add((msg) => { _listBox_Output.Items.Add(msg); });

// Ahora solo llama al delegado:

void pwe_StatusUpdate(string updateMsg) { _listBox_Output.Invoke(add,updateMsg); }

Estoy tratando de entender cómo actualizar una IU de un evento mientras uso el patrón async / await. A continuación se muestra el código de prueba que estoy usando en una aplicación WinForm. Ni siquiera estoy seguro de que esta sea la manera correcta de hacerlo. ¿Qué es necesario para permitir que el método pwe_StatusUpdate actualice la interfaz de usuario? El error de operación de subproceso se produce allí.

Gracias por leer.

// calling code ProcessWithEvents pwe = new ProcessWithEvents(); pwe.StatusUpdate += pwe_StatusUpdate; await pwe.Run(); void pwe_StatusUpdate(string updateMsg) { // Error Here: Cross-thread operation not valid: Control ''_listBox_Output'' accessed from a thread other than the thread it was created on. _listBox_Output.Items.Add(updateMsg); }

-

// Class with long running process and event public delegate void StatusUpdateHandler(string updateMsg); public class ProcessWithEvents { public event StatusUpdateHandler StatusUpdate; public async Task Run() { await Task.Run(() => { for (int i = 0; i < 10; i++) { RaiseUpdateEvent(String.Format("Update {0}", i)); Thread.Sleep(500); } }); } private void RaiseUpdateEvent(string msg) { if (StatusUpdate != null) StatusUpdate(msg); } }

-


Aquí hay otro ejemplo.

async void DoExport() { var rMsg = ""; var t = await Task<bool>.Factory.StartNew(() => ExportAsMonthReport(LastMonth.Name, LastYear.Name, out rMsg)); if (t) { BeginInvoke((Action)(() => { spinnerMain.Visible = false; menuItemMonth.Enabled = true; MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Information, 200); })); } else { BeginInvoke((Action)(() => { spinnerMain.Visible = false; menuItemMonth.Enabled = true; MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Error, 200); })); } }


Debe utilizar el método de Control de Control . Ejecuta algún código en el hilo de Control. También puede verificar la propiedad InvokeRequired para verificar si necesita llamar al método Invoke (comprueba si la persona que llama está en un hilo diferente al que se creó el control).

Ejemplo simple:

void SomeAsyncMethod() { // Do some work if (this.InvokeRequired) { this.Invoke((MethodInvoker)(() => { DoUpdateUI(); } )); } else { DoUpdateUI(); } } void DoUpdateUI() { // Your UI update code here }

En algunos casos, debe verificar la propiedad IsHandleCreated de Control antes de llamar al método Invoke . Si IsHandleCreated devuelve false, IsHandleCreated esperar mientras se creará el identificador de Control


El patrón async tiene soporte para actualizaciones de progreso .

En resumen, su método async puede tomar un IProgress<T> , y su código de llamada pasa en una implementación de esa interfaz (generalmente Progress<T> ).

public class ProcessWithUpdates { public async Task Run(IProgress<string> progress) { await Task.Run(() => { for (int i = 0; i < 10; i++) { if (progress != null) progress.Report(String.Format("Update {0}", i)); Thread.Sleep(500); } }); } } // calling code ProcessWithUpdates pwp = new ProcessWithUpdates(); await pwp.Run(new Progress<string>(pwp_StatusUpdate));