我的问题是:
我有两个线程,我的UI线程和一个工作线程。我的工作线程在一个单独的类中运行,该类由表单实例化,它将自己作为ISynchronizeInvoke
传递给worker类,然后在该接口上使用Invoke
来调用它的事件,这些事件提供状态更新UI以供显示。这很有效。
我注意到我的后台线程似乎运行缓慢,所以我将调用更改为Invoke
到BeginInvoke
,认为“我只是提供进度更新,它不需要要完全同步,不要做任何伤害“除了现在我对进度更新感到奇怪。我的进度条更新,但标签的文本没有更新,如果我更改到另一个窗口并尝试更改回来,它就像UI线程被锁定一样,所以我想知道是否可能是我的进度调用(这种情况非常发生)经常)重载UI线程,以至于它永远不会处理消息。这有可能吗,或者还有其他工作在这里吗?
答案 0 :(得分:3)
你明确地重载了UI线程。
在您的第一个示例中,您(在幕后)向UI线程发送消息,等待处理(这是调用的目的,最终依赖于SendMessage),然后发送另一个。与此同时,其他消息可能已入队(例如WM_PAINT消息)并已处理。
在第二个示例中,通过使用BeginInvoke(最终依赖于PostMessage),您大量排队消息队列中的大量消息,消息泵必须按顺序处理。当然,当它处理成千上万条消息时,它无法处理操作系统消息(WM_PAINT等),这会使您的UI看起来“冻结”
您可能提供了太多状态更新;试着降低反馈水平。
如果您想更好地了解消息在Windows中的工作方式,this就是您的起点。
答案 1 :(得分:1)
一些想法;
Invoke
/ BeginInvoke
获取列表,并在UI上处理缓冲区螺纹BeginInvoke
和匿名方法,你可能会遇到问题......我将在下面添加一个例子BeginEdit
/ EndEdit
,当您进行大量更新时,它会停止重绘UI;相反,它会等到End*
被调用捕获问题...想象(工人):
List<string> stuff = new List<string>();
for(int i = 0 ; i < 50000 ; i++) {
stuff.Add(i.ToString());
if((i % 100) == 0) {
// update UI
BeginInvoke((MethodInvoker) delegate {
foreach(string s in stuff) {
listBox.Items.Add(s);
}
});
}
}
您是否注意到两个线程都在与stuff
交谈? UI线程可以迭代它,而工作线程(已经运行过BeginInvoke
)继续添加。这可能会导致问题。通常不会出现性能问题(除非您捕获异常并花费很长时间来记录它们),但肯定会出现问题。这里的选项包括:
Invoke
同步运行更新