2010-06-16 109 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