在保留一些代码的同时,我发现我们在后台工作者中无限制挂起。该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一起调用该类的表单?或者是否有另一种中断线程供用户输入的方法?
答案 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)