如何在Signal-Slot中放置等待条件?

时间:2011-10-02 13:26:50

标签: c++ qt signals-slots

我正在做一个与网络相关的项目。最近我遇到了这种情况。这只是一个存根

Class My_Class
{
public:
    My_Class();
    void start();
public slots():
    void after_Load_Function();
}

My_Class::My_Class()
{
    //Some initializations
    connect(WebPage,SIGNAL(finished()),this,SLOTS(after_Load_Function()));
}

void My_Class::start()
{
    WebPage->load();
}

void My_Class::after_Load_Function()
{
    //Do something with the finished WebPage
}

int main(int argc,char * argv[])
{
    //Some Qt things

    My_Class a;
    a.start();
}

“WebPage”在完全加载时发出信号“已完成”。 现在的问题是在“webPage”加载之前“start”正在返回。从而控制到达“主”。所以,现在控件应该在“after_Load_Function”完成它的工作之后从“start”返回。因此,我想要以下序列,

  1. main创建My_Class对象A.
  2. 来自A的主要电话“开始”。
  3. 从“WebPage”开始调用加载,它等待“WebPage”发出“完成”,   然后发出的调用依次调用“after_Load_Function”和“after_Load_Function”
      完成它的工作。
  4. 现在,“开始”返回
  5. 主要回报
  6. 但是,我不知道如何制作这种等待条件。我怎么能去做呢?

4 个答案:

答案 0 :(得分:4)

您可以通过运行本地事件循环,让组件处理网络收入并加载页面来实现此目的。当它们发出信号时,您在事件循环上执行一个槽以退出它。

void My_Class::start()
{
    QEventLoop qel;
    QObject::connect(WebPage, SIGNAL(finished()), &qel, SLOT(quit()));

    WebPage->load();
    qel.exec();
}

我之前一直在使用它,它运行正常。我不建议经常使用它,因为它会处理事件,包括那些start的调用者可能不希望在调用start期间处理的事件,所以你需要将此文档记录给其呼叫者。您可以通过将某些标志传递给QEventLoop::exec来阻止某些事件的处理,例如阻止处理用户界面事件。

答案 1 :(得分:0)

你永远不应该等待UI代码。您需要将“主要”功能分解为多个部分,以便后面的部分可以单独执行。

答案 2 :(得分:0)

使用condition variables表示它们的用途。您可以让线程在条件变量上等待,并在收到通知后继续。

答案 3 :(得分:0)

WebPage->load()方法是异步的,这意味着它会立即运行,而不是在加载完成时运行。当你去做其他事情时,操作会在后台运行。

这被视为一件好事,因为它可以让您的应用更具响应性并完成更多工作。例如,如果您的应用程序具有GUI,则可以使用某种动画来更新GUI,以指示正在检索网页。

如果您更喜欢应用程序阻塞的模型,直到页面完全加载,那么请考虑进行此更改:

void My_Class::start()
{
    WebPage->load();
    while (!WebPage->isLoaded())
        Sleep(1);
    after_Load_Function();
}

注意:

  • Sleep功能适用于Windows。如果您使用的是Unix操作系统,则可以使用usleep
  • 由于此功能将有效阻止,直到加载网页,没有理由使用来自网页对象的信号,您可以在等待完成后简单地调用您的处理程序,因为这将使您的处理程序运行同一个帖子。
  • 这样做真的很糟糕。如果您的程序是命令行并且没有GUI和/或事件循环,您可能会侥幸成功,但您应该考虑为您的应用程序设计更好的设计,其中加载网页不会阻止整个应用程序。