我需要调用它:string input_ip_r = listView1.Items[lc].SubItems[1].Text;
所以我用了
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(function));
return;
}
这有效,但现在我把它放到了BackgroundWorker
并使用了这个
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(bw.RunWorkerAsync));
return;
}
它会出错,您一次只能运行一个BackgroundWorker
。
那么我如何在Backgroundworker
?
答案 0 :(得分:8)
1)不要将RunWorkerAsync
作为调用方法。它实际上并没有运行您认为的方法。你真正应该做的是这样的事情:
this.Invoke(new MethodInvoker(MethodToUpdateUI));
MethodToUpdateUI
应该是您创建的一种新方法,专门用于在此上下文中进行任何UI更新。
2)不需要InvokeRequired
。你是一个后台线程。总是需要调用。
老实说,if(invoke required) call myself else do stuff
的整个模式是一个我不喜欢的奇怪结构。应该很少使用InvokeRequired
。你应该几乎总是知道你是在UI线程还是后台线程中,如果你没有,可能是错的(要么你总是在一个或另一个,你只是不知道哪个,或者它不应该是非确定性的)。通常这意味着拥有必须在UI线程中运行的方法。如果你已经在UI线程中,你只需要调用它们,如果你在后台线程中并且知道它,那么你先调用Invoke
。
最重要的是,即使你已经在UI线程中调用它,Invoke
也能正常工作,所以无论你是否调用Invoke
,都没有明显的负面后果'在后台线程中或已经在UI线程中。
3)通常最好将用于解决业务问题的代码与UI代码分开。从DoWork的处理程序中调用代码气味。如果这是接近结束,您可能应该向RunWorkerCompleted
添加事件处理程序。如果您定期调用此更新UI以及工作人员的进度,则应使用ReportProgress
并处理ProgressReported
事件。要从UI获取信息以便在长时间运行的任务中使用,您应该在启动后台任务之前访问它。对于不属于这些情况的特殊情况,使用Invoke
可能是适当的,但剩下的情况应该是罕见的。
答案 1 :(得分:6)
我不太确定你想如何使用这些值,但只是举个例子,你可以在BackgroundWorker
主题中轻松地做到这一点:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string input_ip_r = "";
this.Invoke(new Action(() =>
{
// Don't know what "lc" is (a loop variable?)
input_ip_r = listView1.Items[lc].SubItems[1].Text;
}));
}
请参阅this answer了解其他相同方法(适用于> = .Net 3.5)