вызов метода QThread.exec () необходим в QThread? - PullRequest
6 голосов
/ 26 февраля 2010

Я не звоню exec() в своем коде, но timer и QUdpSocket работают нормально. exec() используется для ожидания продолжения event?

ОБНОВЛЕНИЕ: timer работал, потому что я не звонил moveToThread(this) на QThread, что означало, что QThread фактически все еще был частью main thread. Что касается QUdpSocket, то я использовал опрос functions. Так что не нужно было работать с signals.

СОВЕТ: если вам нужно сделать init, что требует event loop в вашем QThread, вы можете delay звонить moveToThread, пока вам не понадобится signals, то есть практично, когда программа загружается. Вам также не нужно вызывать его в конструкторе (например, вы можете вызвать его внутри run()), просто скопируйте указатель this QThread в переменную и сделайте call позже / в другом месте, используя указатель. *

Ответы [ 3 ]

4 голосов
/ 26 февраля 2010

Ваш таймер и сокет, вероятно, используют основной цикл событий, который запускается при вызове QCoreApplication::exec(). Хотя я уверен, что есть веская причина для запуска цикла событий внутри потока, я не могу придумать его.

Документация QThread гласит:

Каждый QThread может иметь свой собственный цикл обработки событий. Вы можете запустить цикл обработки событий, вызвав exec (); Вы можете остановить это, вызвав exit () или quit (). Наличие цикла событий в потоке позволяет подключать сигналы от других потоков к слотам в этом потоке, используя механизм, называемый подключениями в очереди. Это также позволяет использовать в потоке классы, для которых требуется цикл обработки событий, например QTimer и QTcpSocket. Однако обратите внимание, что в потоке невозможно использовать какие-либо классы виджетов.

Без цикла обработки событий возможно испускание сигналов, которые обрабатываются потоком GUI или другим потоком, содержащим цикл обработки событий. Это подразумевает, что поток должен иметь цикл обработки событий, чтобы его слоты были эффективными. Согласно документации выше, некоторые классы, такие как QTimer , требуют запуска цикла обработки событий, для которого необходимо вызвать QThread::exec(). Другие классы, такие как QTCPSocket , могут работать с циклом событий или без него, в зависимости от используемых функций. В документации для классов должно быть указано, какие требования к ним предъявляются.

2 голосов
/ 26 февраля 2010

Чтобы фактически использовать ваш поток, вместо цикла выполнения QApplication, вы должны вызвать moveToThread(this) в конструкторе потока И поместить цикл выполнения в защищенный метод run() вашего производного класса QThread.

Цикл выполнения отдельных потоков предотвращает загромождение цикла QApplication сигналами и слотами, не относящимися к пользовательскому интерфейсу, и, следовательно, задерживает выполнение слота при нажатии кнопки, например, делая приложение "запаздывающим".

Примечание: Обычно вы всегда подкласс QThread, для получения дополнительной информации см. Qt doc

Редактировать: Qt doc не так, прочитайте эту тему https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

0 голосов
/ 16 августа 2010

Это зависит от ваших программ. Вот пример:

void MyThread::run(){
  Curl * curl = new Curl();
  connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
  connect( curl, SIGNAL(OnDone()), curl, SLOTS(deleteLater()) );
  curl->Download("http://google.com");
  exec(); // this is an event loop in this thread, it will wait until you command quit()
}

void MyThread::OnTransfer(QString data){
  qDebug() << data;
}

Без exec () OnTransfer никогда не будет вызываться. НО, если вы создаете curl вне работы с this (предполагается, что MyThread parent является основным потоком) в качестве родителя:

MyThread::MyThread(){
  curl = new Curl(this);
  connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
  start();
}
void MyThread::run(){
  curl->Download("http://google.com");
}

Этот будет работать, как вы ожидали. Будет вызван OnTransfer.

...