【发布时间】:2010-10-22 20:20:23
【问题描述】:
我正在使用一个相当复杂的 GUI,并试图将大量数据从 GUI 传递到 backgroudWorker。我遇到的问题是从后台工作人员访问一些 GUI 值。例如,如果我尝试获取ComboBox.Text,由于跨线程,我会得到InvalidOperationException。但是,如果我说做TextBox.Text,一切似乎都正常。当然,我对 C# 还很陌生,所以我有点不清楚为什么其中一些可以,而另一些则失败。
我想出了几种方法来解决我的问题,但我正在向有 C# 经验的人寻求最佳实践。
以下是我能想到的解决此问题的几种方法
创建要传递给后台工作线程的所有值的类/结构,并在调用 RunworkAsync 时传递它。我没有发现这很有吸引力,因为我必须为我的 GUI 上的每个页面构建一个类/结构以传递给 backgroundWorker
创建一组具有特定任务的不同后台工作人员。我在传递数据方面仍然存在一些问题,但是我必须传递的数据量被减少了很多。但是,DoWork/ProgressChanged/RunworkerCompleted 的数量明显增加,并不理想。
(这引导我了解我目前正在做的事情)
创建一个委托和方法来捕获信息
private delegate string ReadComboDelegate(ComboBox c);
private string ReadComboBox(ComboBox c)
{
if(c.InvokeRequired)
{
ReadComboDelegate del = new ReadComboDelegate(this.ReadComboBox);
return (string) c.Invoke(del,c);
}
else
{
return c.Text
}
}
然后在DoWork 内,执行string txt = this.ReadComboBox(this.comboBox1); 之类的操作
当您有一个简单的 GUI 并且您不必传递大量数据时,这是一个非常简单的问题。然而,GUI 项目越多、越复杂,这个问题就越大。如果有人有任何信息可以使这更容易,我将不胜感激。
谢谢
【问题讨论】:
-
您使用的是什么版本的 .NET?
-
我认为您在#1 和#2 的正确轨道上。每个线程一个工作单元和一个处理页面的自定义类是不错的设计原则。每个页面只做一个操作吗?你可以结合一些控件吗?您可以在输入信息时将信息加载到后台工作参数类中吗?如果您的 GUI 如此复杂以至于您甚至无法收集所需的所有数据,那么可能需要重新审视 GUI 设计。
-
我认为瑞恩是对的。这段代码听起来可能是个大泥球。
-
我正在运行 .Net 3.5 SP1。这实际上是一个 gui 重新设计,我只是想在进行大量编码之前找出最佳方法,并发现我最好走不同的路线。一个页面每次只执行一个操作,但基于给定 bwWorker 预执行的数据不同。在启动 bwWorker 之前,我禁用当前页面,类似于 msdn 文档。重新启动的唯一方法是取消或等待 bwWorker 完成其当前运行。我想我应该重新审视我的第一次尝试,看起来我从一开始就朝着正确的方向前进。谢谢!
标签: c# multithreading user-interface backgroundworker