Windows窗体:线程安全访问GUI?

时间:2011-08-04 20:17:11

标签: windows forms user-interface delegates

在过去的几个小时里,我一直在与代表和访问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不合适,但这不是重点...

1 个答案:

答案 0 :(得分:2)

这是一个非常标准的死锁案例,对于Control :: Invoke()并不罕见。它只能在UI线程不忙的情况下继续。使用Debug + Windows + Threads并双击Main主题。查看调用堆栈以查看它正在执行的操作。典型的情况是它正在阻塞,等待线程完成工作。这种情况永远不会发生,因为在调用Invoke()之前线程无法完成。

不要阻止UI线程。

考虑使用BackgroundWorker,它的RunworkerCompleted事件很适合在线程完成后执行操作,无需阻塞。