使用backgroundworker进度更新标签

时间:2013-10-08 12:33:54

标签: c# .net multithreading

我在后台工作者的帮助下逐行读取外部exe的控制台,我将每一行控制台分配给一个标签。问题是标签没有使用控制台行更新。代码如下:

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int i = 0;
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = true;
    startInfo.UseShellExecute = false;
    startInfo.FileName = EXELOCATION;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.Arguments = Program.path;
    startInfo.RedirectStandardOutput = true;
    try
    {
        // Start the process with the info we specified.
        // Call WaitForExit and then the using statement will close.
        using (exeProcess = Process.Start(startInfo))
        {
            using (StreamReader reader = exeProcess.StandardOutput)
            {
                string result;
                while ((result = reader.ReadLine()) != null)
                {
                    // object param = result;

                    e.Result = result;
                    bgWorker.ReportProgress(i++);
                }
            }
        }
    }
    catch
    {
        // Log error.
    }
}

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label.Text = e.ToString();
    label.Refresh();
}

我该如何解决这个问题

3 个答案:

答案 0 :(得分:2)

试试这个:

label2.Invoke(new Action(() => { label2.Text = e.ToString(); }));
label2.Invoke(new Action(() => { label2.Refresh(); }));

答案 1 :(得分:0)

该代码可能无效,因为您尝试从非UI线程(也称为后台线程)更新UI元素。

如果您正在使用WPF,则应使用Dispatcher请求在UI线程中更改标签。如果您正在使用其他框架,请尝试该框架的等效类。

在ProgressChanged方法中,请尝试以下方法:

Application.Current.Dispatcher.BeginInvoke(
  DispatcherPriority.Background,
  () => {
    label.Text = e.ToString();
  });

答案 2 :(得分:0)

如果这是在另一个线程中(并且您在winforms应用程序中),则可能需要使用Control.InvokeRequired

public void UpdateProgress (int progress)
{
  if (label.InvokeRequired)
  { 
     this.Invoke(()=> UpdateProgress(progress));
  }
  else
  {
     label.Text = progress.ToString();
  }
}

此方法检查它是否在UI线程上运行,如果不是,则在UI线程上调用自身。如果它已经在UI线程上,它只是更新标签。