Windows Forms: thread safe access to GUI?
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->I开发者_如何学运维nvoke(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...
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.
精彩评论