在后台工作者错误中更改标签文本

Changing label text in background worker Error

我试图在后台工作进程中更改表单上的标签,但它显示未处理的异常。我查看了错误,它说要像这里接受的答案所说的那样调用它:Update label text in background worker winforms

我已经通过更改复选框列表中的值成功地完成了此操作,但是我使用了相同的方法并且对于它不会调用的标签,我在键入它时在代码中看到了红色错误行。

我的后台工作者:

private void bw2_DoWork(object sender, DoWorkEventArgs args)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    func.sshConnect();
    for (int num = 0; num < checklist.Items.Count; num++)
    {
        if (checklist.GetItemChecked(num))
        {
            string project = checklist.Items[num].ToString();
            lblStatus.Text = "Opening " + project + "..."; //error here
            if (func.svnCheckoutProject(project))
            {
                lblStatus.Text = project + " Opened"; //same error here
                func.sshRunCommand("echo " + project + " >> " + Properties.Settings.Default.serverUserFilesPath + Properties.Settings.Default.Username);
            }
            else
            {
                //error message
            }
        }
        worker.ReportProgress(num * (100 / checklist.Items.Count));
    }
}

我试过用这个替换有错误的行,但是在 visual studio 它在调用下给它一条红线并且不允许我构建它。

lblStatus.Invoke((MethodInvoker)delegate { lblStatus.Text = "Opening " + project + "..."; });

Visual studio 出现错误时将我指向此处:MSDN 我将此方法用于复选框列表并且有效,但尝试将其用于标签但它不起作用。

为什么它不起作用或有其他方法可以解决这个问题?

不要从 DoWork 事件更新您的 UI 控件 - 您与 UI 线程处于不同的线程中。可以调用Invoke,但确实不合适。

BackgroundWorker 已经提供了一个在 worker 运行 时定期更新 UI 线程的构造,而您已经在使用它了 - 它是 ReportProgress方法。那是您应该从中更新标签的地方。那里的任何东西都会在主 UI 线程上运行。


您可以将任何 object 传递给 ReportProgess 方法:

worker.ReportProgress(num * (100 / checklist.Items.Count),
                      string.Format("Opening {0} ...", project));

然后将值转换回来并在 ProgressChanged 事件中使用它:

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var message = e.UserState.ToString();

    lblStatus.Text = message;
}

在大多数情况下,您会希望使用 BeginIvoke 而不是 Invoke

    public void changeLabelText(System.Windows.Forms.Label lib, String whateva)
    {
        if (lib.InvokeRequired)
        {
            lib.BeginInvoke(new MethodInvoker(() => changeLabelText(lib, whateva)));
        }
        else
        {
            lib.Text = whateva;
        }
    }

并调用 DoWork 中的方法

private void bw_DoWork(object sender, DoWorkEventArgs args)
{
//do something
//change the text of a label lb1
changeLabelText(lb1, "I'm reporting some progress....");
}