2010-06-16 111 views
11

我正在处理一个应用程序,它将文件的内容上传到服务器。等待信号

将文件上传到服务器我使用'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对象并开始上传。

在上传该文件,如果用户关闭窗体,然后在我称之为“文件传输”停止后,我删除“文件传输”对象的窗口的析构函数。

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

请帮我: 如何“停止()”功能等到上传()函数完成

回答

19

从我的代码中可以看到,您正在执行QEventLoop,但实际上并没有将其“退出”插槽连接到任何信号。以下面的例子为例,登录是一个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交手,但我相信这就是你的意思!祝你好运!

+0

是的,我加入了代码,只要我们得到完成插槽退出事件循环。但是如果用户停止连接并删除对象,则下载文件时会出现问题。但上传功能尚未完成。在这个时候它会崩溃。 – 2010-06-16 11:09:22

0

我认为你需要添加类似的东西在你的上传功能:

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

希望它能帮助。

0

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

所以,你可以写:

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; 
}; 
+0

我可能是错的,但我不认为这将工作,因为gcl倒计时闩锁是为了阻止线程。put()调用发生在主GUI线程中,然后QNetworkAccessManager在单独的线程中获取网页,完成的()插槽在主GUI线程中执行。因此,在示例中使用此代码只会导致整个应用程序锁定。可以将完成的槽移入不同的线程,但这需要更多的代码,这里没有显示。 – Ph0t0n 2018-03-04 01:20:31