我想使用BackgroundWorker进行后台操作,因为我认为在更新WinForm-Controls时不需要处理“BeginInvoke”等。是对的吗?据我所知,您可以使用ProgressChanged和RunWorkerCompleted事件处理程序直接更新WinForms控件。
但我不能,我虽然得到以下例外:
从
上创建的线程以外的线程访问的控件名称
一些代码:
public partial class ConfigurationForm : Form
{
public ConfigurationForm()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
label1.Text = String.Empty;
// [...]
}
private void StartButton_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy != true)
{
label1.Text = "Converting...";
backgroundWorker1.RunWorkerAsync();
}
}
private void CancelButton_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation == true)
{
backgroundWorker1.CancelAsync();
}
progressBar1.Dispose();
this.Close();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
// EXCEPTION here, why?
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Converter c = new Converter();
c.Start(worker, e);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// EXCEPTION in all cases, why?
if (e.Cancelled == true)
{
label1.Text = "Canceled";
}
else if (e.Error != null)
{
label1.Text = "Error: " + e.Error.Message;
}
else
{
label1.Text = "Done!";
}
}
}
我不得不说,这不是WinForms应用程序,而是VSTO PowerPoint加载项。当用户单击PowerPoint的功能区栏中的图标时,上面的表单由加载项创建:
//Do I need [STAThread] here? but doesn't seem to work anyway
private void button1_Click(object sender, RibbonControlEventArgs e)
{
ConfigurationForm config = new ConfigurationForm();
config.Show();
}
你能告诉我这里有什么问题吗?
答案 0 :(得分:1)
我发布了链接,但实际上并不认为这是最好的解决方案。很明显,失败的原因是您从未调用Application.Run()或使用Form.ShowDialog()。您可以如图所示明确分配上下文,但如果您不正确,则可能会遇到一些非常棘手的问题。就像分配不止一次一样。
更好的解决方法是让它自动安装。然后确保您创建的任何表单只有在以前没有完成时才会安装它。把它放在表单创建代码的前面:
WindowsFormsSynchronizationContext.AutoInstall = true;
如果代码重复出现,那么你将不会创建另一个实例,并可能搞砸了线程的ExecutionContext。
请将ShowDialog()视为另一个修复程序。如果我没有弄错的话,你现在也会遇到标签和快捷键击的问题。
答案 1 :(得分:0)
您对Windows窗体的假设是正确的。它的工作方式是BackgroundWorkers
使用当前线程的SynchronizationContext
。在Windows应用程序中,这将是WindowsFormsSynchronizationContext
,它会为您进行编组。
在VSTO应用中,它不会。它可能只是默认的,它只是执行方法。 Hans Passant的链接提供了使其按预期工作所需的代码。即:
System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
...create and start your background worker here...