Windows 窗体:对 GUI 的线程安全访问?
在过去的几个小时里,我一直在努力处理委托和访问 Windows 窗体控件 (C++),我在其中使用了本教程(第一个线程安全方法):http://msdn.microsoft.com/en-us/library/ms171728.aspx#Y190
更改文本框和标签效果很好,但是当我想向另一个人显示或隐藏整个 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 子句为 true,因此调用 Invoke。但通常当 if 子句返回 false 时,应自动调用 showUI 方法,但这种情况并未发生。所以 GUI 既不显示也不隐藏。
是否有必要使用委托来显示/隐藏 GUI,或者我可以从每个可能的线程中执行此操作吗?如果需要委托,为什么showUI不执行第二次?
谢谢, 马丁
编辑:好吧,SetTextDelegate 这个名字不合适,但这不是重点......
in the last hours I've struggled with delegates and accessing Windows Forms controls (C++) where I've used this tutorial (the first thread safe method): http://msdn.microsoft.com/en-us/library/ms171728.aspx#Y190
Changing TextBoxes and Labels works perfectly but when I want to show or hide the whole GUI from another thread this fails.
I use the following methode (which is part of the GUI class):
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();
}
}
In the first call the if-clause is true so Invoke is called. But usually the showUI method should be called a second time automatically where the if-clause returns false, but this is not happening. So the GUI is neither shown nor hiden.
Is it necessary to show/hide the GUI with a delegate or can I do it from every possible thread? If a delegate is necessary, why is showUI not executed a second time?
Thanks,
Martin
edit: okay the name SetTextDelegate is not appropriate but this is not the point...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个非常标准的死锁情况,对于 Control::Invoke() 来说并不罕见。仅当 UI 线程不忙时它才能继续。使用“调试”+“Windows”+“线程”,然后双击“主线程”。查看调用堆栈以了解它在做什么。典型的情况是它处于阻塞状态,等待线程完成工作。这种情况永远不会发生,因为在 Invoke() 调用返回之前线程无法完成。
不要阻塞 UI 线程。
考虑使用BackgroundWorker,它的RunworkerCompleted事件很适合在线程完成后做一些事情,消除了阻塞的需要。
This is a pretty standard case of deadlock, not uncommon with Control::Invoke(). It can only proceed if the UI thread is not busy. Use Debug + Windows + Threads and double-click the Main thread. Look at the call stack to see what it is doing. The typical case is that it is blocking, waiting for the thread to finish the job. That will never happen since the thread can't complete until the Invoke() call returns.
Don't block the UI thread.
Consider using BackgroundWorker, its RunworkerCompleted event is nice to do stuff after the thread completes, removing the need to block.