【问题标题】:update a control in UI with running background Thread in Winforms在 Winforms 中运行后台线程更新 UI 中的控件
【发布时间】:2012-06-26 16:11:37
【问题描述】:

我在我的 Winform 中使用后台工作线程,在我的 Do_Work 事件中我正在计算一些东西,我需要的是同时我想更新主/UI 线程中的标签?如何做到这一点?

我想通过 Do_Work 事件更新我的标签...

【问题讨论】:

  • 查看 ReportProgress 方法和 ProgressChanged 事件。您可以将字符串作为用户数据传递。

标签: c# winforms multithreading


【解决方案1】:

在 WinForms(WPF 也是)中,UI 控件只能在 UI 线程中更新。你应该这样更新你的标签:

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

【讨论】:

    【解决方案2】:

    Do_Work 方法中,您可以使用对象的 Invoke() 方法在其 UI 线程上执行委托,例如:

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

    ...然后确保将这样的方法添加到您的类中:

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

    【讨论】:

      【解决方案3】:

      希望对你有所帮助:

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

      【讨论】:

      • 很抱歉,但这段代码真的没有帮助,即使这段代码在行 - “backgroundWorker1.ReportProgress(0);”中给出了一个异常;
      • 您是否将 WorkerReportsProgress 设置为 true ?如果你这样做了,请给我异常消息
      【解决方案4】:

      您在用户界面(标签)更新期间面临跨线程异常的问题,因为它(UI)在不同的线程(主线程)中。您可以使用许多选项,如 TPL、线程池、等等等等,但方法很简单做你想做的就是在你的 Do_Work 方法中写一个简单的 Action

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

      【讨论】:

        【解决方案5】:

        使用扩展方法的更通用的解决方案。这允许您更新任何控件的 Text 属性。

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

        你可以使用这样的方法:

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

        【讨论】:

          猜你喜欢
          • 2013-06-04
          • 1970-01-01
          • 2010-10-13
          • 2018-07-16
          • 1970-01-01
          • 1970-01-01
          • 2012-04-24
          • 1970-01-01
          • 2015-03-20
          相关资源
          最近更新 更多