2

我需要调用这个: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一个。

那么如何在 中调用 whileBackgroundworker呢?

4

2 回答 2

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首先调用。

最重要的是,Invoke即使您已经在 UI 线程中调用它也可以正常工作,因此Invoke无论您是在后台线程中还是已经在 UI 线程中,调用都不会产生明显的负面影响。

3) 通常最好将解决业务问题的代码与 UI 代码分开。从 DoWork 的处理程序中调用是代码异味。如果这即将结束,您可能应该将事件处理程序添加到RunWorkerCompleted. 如果您定期调用它以使用工作人员的进度更新 UI,那么您应该正在使用ReportProgress和处理该ProgressReported事件。要从 UI 获取信息以用于长时间运行的任务,您应该在启动后台任务之前访问它。对于不属于上述任何一种的特殊情况,使用 可能是合适的Invoke,但其余情况应该很少见。

于 2012-12-19T20:18:49.900 回答
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;
    }));
}

请参阅此答案以了解其他相同的方法(适用于 >= .Net 3.5)

于 2012-12-19T21:26:39.630 回答