从背景工作者的文件对话框

时间:2012-05-16 18:24:06

标签: c# multithreading dialog backgroundworker

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

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 个答案:

答案 0 :(得分:3)

不建议从后台工作者DoWork事件处理程序调用UI。 BackgroundWorker旨在对非UI线程进行工作以保持UI响应。在使用BackgroundWorker启动RunWorerkAsync对象之前,您应该询问任何文件信息。

答案 1 :(得分:1)

您要做的是捕获UI线程上的SynchronizationContext并将其传递给后台工作者。 BackgroundWorker可以在上下文中调用Send()(同步,如Invoke)和Post()(异步,如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);
        }
    );
}

答案 2 :(得分:0)

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

也许,只需传回一些状态result(或者抛出一个非常有针对性的特殊异常,你可以在UI中处理)?

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

很抱歉,没有更具体的代码,但根据系统的架构方式,它可以采用多种不同的方式。

答案 3 :(得分:-2)

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