我有一个带有名为 MainForm 的窗体的 winform。 我有一个名为 ObjMgr 的静态类。 在 ObjMg 中,我还有其他几个静态类、值,但现在不重要。
在 ObjMgr 类中,我还有一个 static void Pulse() 方法,用于填充 ObjMgr 中的其他静态类。这种脉冲方法必须经常运行,比如 0,033 秒。
在 MainForm 上,我放置了一个开始按钮,在单击事件时,它开始在另一个线程上脉冲我的 ObjMgr。
Pulser = new System.Threading.Thread(new System.Threading.ThreadStart(ObjMgr.StartPulsing));
Pulser.IsBackground = true;
Pulser.Start();
我的 ObjMgr.StartPulsing 方法来源:
while(true)
{
ObjMgr.Pulse();
System.Threading.Thread.Sleep(30);
}
我的 Pulser 方法来源:
//here I update all my data in ObjMgr
// Its need to be fast, I have some while, and switch statements here.
// complicated code here :D The main thing is, its populating my classes with data.
现在我的脉冲发生器正在运行,并使我的静态类数据保持最新。 这是很不错的。下一步,我想在我的表单 (UI) 上显示来自更新的 ObjMgr 类的一些数据。在我的表单上,我有大约 20 个标签,2 个 ProgressBar 值,我想经常更新,就像 Pulsator。 (0,033 秒)
很明显更新我的标签,从 Pulsator 方法本身,但我担心它会减慢我的 Pulsator,我不想要它。所以,我需要一些技巧,如何做这件事。我在想,我实现了计时器,我将间隔设置为 30,然后在滴答事件上我从 ObjMgr 读取我的数据,并显示修改标签。它工作正常,但小车,因为一些同步问题。 如果您了解我的问题,能否给我一些反馈,或如何改进的提示?
如果我尝试从 Pulse() 方法本身更新我的标签,它会减慢我的 Pulse() 方法吗?如果没有,我如何从另一个线程更新 MainForm 上的 20 个标签?
最佳答案
考虑到您的情况的时间标准,我会避免从工作线程启动 UI 更新。原因有两个。首先,很可能会对线程的时序特性产生一些影响。其次,您必须使用昂贵的编码(marshal)处理操作(通过 Control.Invoke
)将 UI 更新操作传输到 UI 线程。
在这种情况下,最好的办法是将执行 UI 更新所需的所有信息打包到一个类中,然后将其存储在一个共享变量中。然后让您的 UI 线程以适合您的应用程序的时间间隔轮询此共享变量。1
这种方法有几个优点。
- 与
Control.Invoke
或Control.BeginInvoke
紧密耦合的方法相反,UI 和工作线程保持松散耦合。 - UI 线程不会阻碍工作线程的进程。
- 工作线程不能支配 UI 线程更新所花费的时间。
- UI 和工作线程执行操作的时间间隔可以保持独立。
- 工作线程不能超过 UI 线程的消息泵。
1按照您的建议尽快更新 UI 听起来不是个好主意。 UI 用于人机交互,因此没有人会关心甚至不会注意到它更新得如此之快。
关于c# - 从 MainThread 修改控件(需要专业人士的一些理论确认),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3857001/