2011-04-10 61 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