2011-04-10 70 views
1

我有一個簡單的應用程序使用一個工作線程。 此工作線程已啓動並初始化DownloadManager,它負責從網上下載文件。 在我的主要應用程序類中,我已完成()SIGNAL在發送之前在DownloadManager完成的線程。如何讓QThread等到工作完成,然後完成?

我的問題是如何使工作線程等待,直到下載管理器完成其工作。

下面是示例代碼:

class Main 
{ 
    m_DownloadWorker = new DownloadWorker(this); 
    QObject::connect(pm_hotosDownloadWorker, SIGNAL(finished()), this, SLOT(DownloadWorkerFinished())); 
    m_DownloadWorker->Execute(); 
    // do i need to do here something so the thread will wait ? 

    ..... 


    void Main::DownloadWorkerFinished() 
    { 
     Log("DownloadWorkerFinished"); 
    } 
}; 


class DownloadWorker : public QThread 
{ 
    void DownloadWorker::Execute() 
    { 

     // do i need to do here somthing so the thread will wait ? 
     start(); 
    } 

    void DownloadWorker::run() 
    { 
     // do i need to do here somthing so the thread will wait ? 
     DownloadManager* pDownloadManager = new DownloadManager(this); 
     pDownloadManager->download(); 


    } 
}; 

class DownloadManager: public QObject 
{ 
    // downloading stuff using Qt networkmanager 

    ..... 
    ..... 
} 
+0

這很混亂。 1)pm_hotosDownloadWorker是什麼? 2)QObject :: connect(pm_hotosDownloadWorker,SIGNAL(finished()),this,SLOT(DownloadWorkerFinished()))是什麼?意思?在DownloadWorker :: start()中會發生什麼? 3)爲了弄清楚你是否需要做一些事情來讓線程等待,通過比較你的期望和實際發生的事情/文件說明應該發生的事情來測試你是否需要某些東西。 4)爲什麼有3個點要阻止執行? – 2011-04-10 09:20:56

+0

1)我修好了它2)它只是打印按摩,線程完成3)... 4)我什麼線程將只完成從DownloadManager的下載完成 – user63898 2011-04-10 10:23:06

回答

3

您可以使用QThread::exec()調用在事件循環中運行您的線程。線程將運行它,直到通過調用QThread::exit()告訴線程退出。因此,一些示例代碼可以是這樣的:

void DownloadWorker::run() 
{ 
    DownloadManager* pDownloadManager = new DownloadManager(this); 
    connect(pDownloadManager, SIGNAL(finished()), SLOT(exit())); 
    connect(pDownloadManager, SIGNAL(error()), SLOT(exit())); 
    pDownloadManager->download(); 
    exec(); 
} 

這會向你保證,你的線程不會退出,直到你的下載管理器的「已完成()」信號發出。

注意:這裏我舉了一個如何解決您的問題的例子,但我不知道您的整個應用程序代碼。這意味着不保證這些代碼是線程安全的並且是一致的。您需要自己處理互斥鎖和所有正確的同步。要特別小心 !使用這樣的「低級」線程API可以很好地理解多線程。

希望有幫助

4

在情況下,當你有當完成一個異步操作,其發出的信號,可以始終使用QEventLoop到「轉」異步操作進入同步與當前線。它仍然是異步的,但線程將「等待」它完成。

QNetworkAccessManager nam; 
QEventLoop loop; 
QNetworkReply *reply = nam.get(request); 
connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); 
loop.exec(); 

所以基本上你把這個放在你想要同步做網絡請求的你的DownloadManager類中。一旦循環的quit插槽被調用,exec()將返回。

+0

我已經在我的功能完成SLOT,如何我可以這樣做嗎? – user63898 2011-04-10 10:30:33

+0

你的意思是信號,對吧?您可以將多個插槽連接到單個信號,沒問題。 – 2011-04-10 11:51:40

+0

在信號連接到循環退出槽之前調用nam.get()。在調用loop.exec()或connect statemet之前調用完成的信號是不可能的。問題1:如果信號在連接之前被刪除會發生什麼? Q2:在exec()和connect()之後發出信號時會發生什麼? @TamásSzelei – 2017-02-21 15:30:20