在后台工作者错误中更改标签文本
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....");
}
我试图在后台工作进程中更改表单上的标签,但它显示未处理的异常。我查看了错误,它说要像这里接受的答案所说的那样调用它: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....");
}