在后台工作者期间调用

时间:2012-12-19 20:13:28

标签: c# background invoke worker

我需要调用它: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

中调用

2 个答案:

答案 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)