Updating UI from events using asyc await

别说谁变了你拦得住时间么 提交于 2019-12-18 12:49:37

问题


I am trying to understand how to update a UI from an event while using async/await pattern. Below is the test code I am using on a WinForm app. I am not even sure this is the right way to go about it. What is necessary to allow the pwe_StatusUpdate method to update the UI? The cross-thread operation error is thrown there.

Thanks for reading.

 // 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);
        }
   }

-


回答1:


The async pattern has support for progress updates.

In short, your async method can take an IProgress<T>, and your calling code passes in an implementation of that interface (usually 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));



回答2:


You should use Invoke method of Control. It executes some code in Control's thread. Also you can check InvokeRequired property to check if you need to call Invoke method (it checks if the caller is on a different thread than the one the control was created on).

Simple example:

void SomeAsyncMethod()
{
    // Do some work             

    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker)(() =>
            {
                DoUpdateUI();

            }
        ));
    }
    else
    {
        DoUpdateUI();
    }
}

void DoUpdateUI()
{
    // Your UI update code here
}

In some cases you should check the IsHandleCreated property of Control before calling Invoke method. If IsHandleCreated returns false then you need wait while Control's handle will be created




回答3:


//Just declare a delegate like so

delegate void Add(string msg);

//Then declare the delegate method like so:

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

//Now just call the delegate:

void pwe_StatusUpdate(string updateMsg)
    {

      _listBox_Output.Invoke(add,updateMsg);
    }



回答4:


Here is another example

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);
          }));
    }
}


来源:https://stackoverflow.com/questions/17631275/updating-ui-from-events-using-asyc-await

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!