Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# in Async Task change Label Text

The following Code does not change the Text and stops executing the Task

private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Test";
        Task.Run(() => MyAsyncMethod());
    }

    public async Task MyAsyncMethod()
    {
        label1.Text = "";
        //everything from here on will not be executed
    }

would be really handy if you could use async together with the UI

like image 811
save_jeff Avatar asked Dec 06 '22 21:12

save_jeff


2 Answers

for accessing a GUI control through a second thread you need to invoke. following example shows how to set a label's text properly

  private void setLabel1TextSafe(string txt)
  { 
       if(label1.InvokeRequired)
           label1.Invoke(new Action(() => label1.Text = txt));
       else
           label1.Text = txt;
  }

I hope this solves your problem

like image 115
leAthlon Avatar answered Dec 11 '22 09:12

leAthlon


would be really handy if you could use async together with the UI

The design of async was carefully done so you can use it naturally with the UI.

in my code i run a function that does a lot of IO and stuff that takes a long time

If you have asynchronous I/O methods (which you should), then you can just do this:

private async void button1_Click(object sender, EventArgs e)
{
  label1.Text = "Test";
  await MyMethodAsync();
}

public async Task MyMethodAsync()
{
  label1.Text = "";
  await ...; // "lot of IO and stuff"
  label1.Text = "Done";
}

That's the most natural approach.

However, if you need to run code on a background thread (e.g., it's actually CPU-bound, or if you just don't want to make your I/O operations asynchronous like they should be), then you can use IProgress<T>:

private void button1_Click(object sender, EventArgs e)
{
  label1.Text = "Test";
  var progress = new Progress<string>(update => { label1.Text = update; });
  await Task.Run(() => MyMethod(progress));
}

public void MyMethod(IProgress<string> progress)
{
  if (progress != null)
    progress.Report("");
  ...; // "lot of IO and stuff"
  if (progress != null)
    progress.Report("Done");
}

Under no circumstances should modern code use Control.Invoke or (even worse) Control.InvokeRequired.

like image 36
Stephen Cleary Avatar answered Dec 11 '22 10:12

Stephen Cleary