【问题标题】:waiting for a signal等待信号
【发布时间】:2010-06-16 09:50:09
【问题描述】:

我正在开发一个将文件内容上传到服务器的应用程序。

要将文件上传到服务器,我使用的是“QNetworkAccessManager”类。由于它以异步方式工作,因此我使用 QEventLoop 将其更改为以同步方式工作。

Class FileTransfer
{
Public : 
     QNetworkAccessManager mNetworkManager;
     Void Upload(QNetworkRequest request, QIODevice *data)
     {
           responce = mNetworkManager.put(request, data);
           EventLoop.exec();
           ReadResponce(responce);
      }

      Void Stop()
      {
            responce ->close();
      }
}

在我的示例应用程序中,我有 2 个窗口。第一个选择文件,第二个显示进度。

当用户点击第一个窗口中的上传按钮时,将显示第二个窗口,然后我创建 FileTransfer 对象并开始上传。

在上传文件时,如果用户关闭表单,然后在窗口的析构函数中调用“FileTransfer”的停止,然后删除“FileTransfer”对象.

但是这里的 Upload() 函数还没有完成,所以它会崩溃。

请帮助我: 如何在 'stop()' 函数中等待直到 Upload() 函数完成

【问题讨论】:

    标签: qt signals signals-slots qt-signals


    【解决方案1】:

    从您的代码中可以看出,您正在执行 QEventLoop,但实际上并未将其“退出”插槽连接到任何信号。以下面为例,login 是一个 QHttp - 代码取自不同的东西 - 但原理是适用的。

    /* Create the QEventLoop */
    QEventLoop pause;
    /* connect the QHttp.requestFinished() Signal to the QEventLoop.quit() Slot */
    connect(&login, SIGNAL(requestFinished( int, bool )), &pause, SLOT(quit()));
    /* The code that will run during the QEventLoop */
    login.request(header,&logmein,&result);
    /* Execute the QEventLoop - it will quit when the above finished due to the connect() */
    pause.exec();
    

    如果我没记错的话,这可以应用于您的代码,就像这样......

    /* connect the signal to the relevant slot */
    connect(&mNetworkManager, SIGNAL(finished( QNetworkReply )), &EventLoop, SLOT(quit()));
    /* Execute the code that will run during QEventLoop */
    responce = mNetworkManager.put(request, data);
    /* Execute the QEventLoop */
    EventLoop.exec();
    

    如果我弄错了您的问题,我们深表歉意!我只是在休息后再次掌握qt,但我相信这就是你的意思!祝你好运!

    【讨论】:

    • 是的,我添加了代码以在我们获得完成槽后立即退出事件循环。但问题在于如果用户停止连接并删除对象,则在下载文件时。但上传功能尚未完成。这时候它会崩溃。
    【解决方案2】:

    我认为您需要在上传功能中添加类似的内容:

    if (upf->openFile())
    {
        reply = manager->post(request, upf);
        connect(reply, SIGNAL(uploadProgress(qint64,qint64)), this, SIGNAL(progress(qint64,qint64)));
        connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
        isInProgress = true;
        emit started();
    } else
    {
        emit finished(true, false, tr("Error: can't open file %1").arg(filename));
    }
    

    这里是全文代码:datacod-qt-tools

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      就个人而言,我建议不要使用这些答案中的任何一个。 将倒计时锁存器连接到信号就足够了。

      所以你可以写:

      Latch latch( 1 );
      QObject::connect( reply, SIGNAL(finished()),
                        &latch, SLOT(countDown()) );
      
      latch.wait();
      

      为此,您需要一个包装器:

      class Latch : public QObject {
          Q_OBJECT
      public:
          Latch( uint count );
          void wait();
      public slots:
          void countDown();
      private:
          gcl::countdown_latch _latch;
      };
      

      【讨论】:

      • 我可能是错的,但我认为这不会起作用,因为 gcl 倒计时锁存器用于阻塞线程。 put() 调用发生在主 GUI 线程中,然后 QNetworkAccessManager 在单独的线程中获取网页,并且 finished() 槽在主 GUI 线程中执行。因此,在示例中使用此代码只会导致整个应用程序锁定。可以将完成的插槽移动到不同的线程中,但这需要更多代码,此处未显示。
      猜你喜欢
      • 1970-01-01
      • 2012-06-29
      • 2014-04-10
      • 2014-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      相关资源
      最近更新 更多