在过去的几个小时里,我一直在与代表和访问Windows Forms控件(C ++)进行斗争,我已经使用了本教程(第一个线程安全方法):http://msdn.microsoft.com/en-us/library/ms171728.aspx#Y190
更改TextBoxes和Labels可以很好地工作,但是当我想从另一个线程显示或隐藏整个GUI时,这会失败。
我使用以下方法(它是GUI类的一部分):
System::Void UI::showUI(boolean value) {
if (this->InvokeRequired) {
SetTextDelegate^ d = gcnew SetTextDelegate(this, &UI::showUI);
this->Invoke(d, gcnew array<Object^> { value });
} else {
if (value == true)
this->Show();
else
this->Hide();
}
}
在第一次调用中if-clause为true,因此调用Invoke。但是通常应该在if-clause返回false的情况下自动调用showUI方法,但这不会发生。因此GUI既不显示也不隐藏。
是否需要使用委托显示/隐藏GUI,还是可以从每个可能的线程中执行此操作?如果需要委托,为什么showUI不会再次执行?
谢谢, 马丁
编辑:好的名字SetTextDelegate不合适,但这不是重点...
答案 0 :(得分:2)
这是一个非常标准的死锁案例,对于Control :: Invoke()并不罕见。它只能在UI线程不忙的情况下继续。使用Debug + Windows + Threads并双击Main主题。查看调用堆栈以查看它正在执行的操作。典型的情况是它正在阻塞,等待线程完成工作。这种情况永远不会发生,因为在调用Invoke()之前线程无法完成。
不要阻止UI线程。
考虑使用BackgroundWorker,它的RunworkerCompleted事件很适合在线程完成后执行操作,无需阻塞。