Как заставить QThread ждать, пока работа не будет выполнена, а затем закончить? - PullRequest
1 голос
/ 10 апреля 2011

У меня есть простое приложение, которое использует один рабочий поток. Этот рабочий поток запускается и инициализирует DownloadManager, который отвечает за загрузку файлов из сети. В моем главном классе приложения у меня есть сигнал finish () в потоке, который испускается до завершения DownloadManager.

У меня вопрос, как заставить рабочий поток ждать, пока DownloadManager завершит свою работу.

Вот пример кода:

 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 

     .....
     .....
 }

Ответы [ 2 ]

4 голосов
/ 10 апреля 2011

В тех случаях, когда у вас есть сигнал, который излучается при завершении асинхронной операции, вы всегда можете использовать QEventLoop, чтобы «превратить» асинхронную операцию в синхронную с текущим потоком. Он все еще асинхронный, но поток будет «ждать» его завершения.

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

Таким образом, вы в основном помещаете это в свой класс DownloadManager, где хотите синхронно выполнять сетевой запрос. exec() вернется после вызова слота quit цикла.

3 голосов
/ 10 апреля 2011

Вы можете использовать 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();
 }

Это гарантировало бы, что ваш поток не завершит работу до тех пор, пока не будет выдан сигнал "done ()" вашего DownloadManager.Здесь я привожу пример того, как решить вашу проблему, но я не знаю весь код вашего приложения.Это означает, что нет гарантии, что этот код является потокобезопасным и непротиворечивым.Вы должны позаботиться о мьютексах и всей правильной синхронизации самостоятельно.Будь очень осторожен !Работа с таким «низкоуровневым» API потока требует хорошего понимания многопоточности.

Надеюсь, что это поможет

...