3

在维护一些代码时,我发现我们在后台工作人员中有一个无限挂断。工作人员需要访问脚本文件。如果没有定义脚本文件,则编写原始代码以弹出文件对话框,以允许用户选择一个。它看起来像这样:

private void bgworker_DoWork(object sender, DoWorkEventArgs e)
{
    ... snip ...

    if (String.IsNullOrWhitespace(scriptFile))
    {
         scriptFile = PromptForScript();
    }

    ... snip ...
}

private string PrompForScript()
{
    string script = "";
    OpenFileDialog openDialog = new OpenFileDialog();

    if (openDialog.ShowDialog() == DialogResult.OK)
    {
        script = openDialog.FileName;
    }

    return script;
}

我已经阅读了一些关于 的内容MethodInvoker,但是几乎所有的调用方法都要求您从控件中调用它们。有问题的后台工作人员从一个单独的类运行,该类不扩展Control. 我是否为此使用与 bgworker 一起调用类的表单?还是有另一种方法可以中断用户输入的线程?

4

4 回答 4

3

不建议从后台工作人员 DoWork 事件处理程序调用 UI。 BackgroundWorker旨在在非 UI 线程上工作以保持 UI 响应。在BackgroundWorker使用RunWorkerAsync.

于 2012-05-16T18:45:14.683 回答
1

您要做的是在 UI 线程上捕获SynchronizationContext并将其传递给后台工作人员。BackgroundWorker 可以在上下文上调用Send()(同步, like Invoke) 和Post()(asynchronous, like BeginInvoke) 以调用回正确的 UI 线程。也就是说,在这种情况下可能不需要 BackgroundWorker - 常规线程池线程就可以了。

来自http://msmvps.com/blogs/manoj/archive/2005/11/03/74120.aspx的这段代码(稍作修改)应该给你一个大致的想法:

private void button1_Click(object sender, EventArgs e)
{
    // Here we are on the UI thread, so SynchronizationContext.Current
    // is going to be a WindowsFormsSynchronizationContext that Invokes properly
    ctx = SynchronizationContext.Current;
    ThreadPool.QueueUserWorkItem(
        // This delegate is going to be invoked on a background thread
        s => {
            // This uses the context captured above to invoke
            // back to the UI without the "messy" referencing 
            // of a particular form
            ctx.Send(s2 =>
            {
               // Interact with your UI here- you are on the UI thread
            },null);
        }
    );
}
于 2012-05-16T18:45:32.367 回答
0

如果某个表单在另一个使用 BGworker 的类中启动了一个长时间运行的进程,为什么表单(或演示者,取决于 UI 架构)不处理错误状态的处理?

也许,只是传回一些状态结果(或抛出一个非常有针对性的、特定的异常,您可以在 UI 中处理)?

让后台工作人员确定是否存在错误,但将错误(尤其是显示消息框的 UI 部分)交给上层。

抱歉,这没有更具体的代码,但根据您的系统的架构方式,它可能会有很多不同的方式。

于 2012-05-16T18:54:33.777 回答
-2

好吧,Form该类有一个Invoke方法,因此将表单实例传递给后台工作类应该可以。

于 2012-05-16T18:40:24.270 回答