简体   繁体   中英

update a control in UI with running background Thread in Winforms

I am using Background Worker Thread in my Winform, inside my Do_Work Event I am calculating something, what I need the thing is that simultaneously I would like to update a label which is in main/UI thread ? how to achieve this?

I want to update my label from Do_Work event...

In WinForms (WPF as well) UI controls can only be updated in the UI thread. You should update your label this way:

public void UpdateLabel(String text){
    if (label.InvokeRequired)
    {
        label.Invoke(new Action<string>(UpdateLabel), text);
        return;
    }      
    label.Text = text;
}

Inside your Do_Work method, you can use the object's Invoke() method to execute a delegate on its UI thread, eg:

this.Invoke(new Action<string>(UpdateLabel), newValue);

...and then make sure to add a method like this to your class:

private void UpdateLabel(string value)
{
    this.lblMyLabel.Text = value;
}

I hope this help :

  int x = 0;
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

        label1.Text = x.ToString();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        x++;
        //you can put any value
        backgroundWorker1.ReportProgress(0);
    }

    private void button6_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

You are facing a problem of Cross thread exception during User Interface(Label) update ,because it(UI) is in different Thread(mainThread).You can go with many options like TPL ,ThreadPool ,blah blah but simple way to do what you want is write a simple Action in your Do_Work method as

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{
    x++;
    //you can put any value
    Action = act =()=>
           {
              label.Text = Convert.ToString(x);
           };
     if (label.InvokeRequired)
         label.BeginInvoke(act);
     else
          label.Invoke(act);
    backgroundWorker1.ReportProgress(0);
}

A more generic solution using an Extension method. This allows you to update the Text property of any control.

public static class ControlExtensions
{
   public static void UpdateControlText(this Control control, string text)
   {
      if (control.InvokeRequired)
      {
         _ = control.Invoke(new Action<Control, string>(UpdateControlText), control, text);
      }

      control.Text = text;
   }

   public static void UpdateAsync(this Control control, Action<Control> action)
   {
      if(control.InvokeRequired)
      {
         _ = control.Invoke(new Action<Control, Action<Control>>(UpdateAsync), control, action);
      }

      action(control);
   }
}

And you can use the methods like this:

TextBox1.UpdateControlText(string.Empty); // Just update the Text property

// Provide an action/callback to do whatever you want.
Label1.UpdateAsync(c => c.Text = string.Empty); 
Button1.UpdateAsync(c => c.Text == "Login" ? c.Text = "Logout" : c.Text = "Login");
Button1.UpdateAsync(c => c.Enabled == false);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM