Относительно первого (не moveToThread
) примера ...
Беглый взгляд на источник Qt для QBasicTimer::start
показывает следующее ...
void QBasicTimer::start(int msec, QObject *obj)
{
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
// ...
if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) {
qWarning("QBasicTimer::start: Timers cannot be started from another thread");
return;
}
Таким образом, ожидается, что его второй аргумент obj
будет иметь сродство к потоку, равное текущему потоку.
В вашей реализации Worker::run
, однако, у вас есть ...
timer.start(1000, this);
В этом контексте текущий поток - это новый поток, созданный экземпляром QThread
, но this
ссылается на экземпляр QWorker
, созданный MainWidget
в главном потоке GUI. Отсюда и предупреждение.
Редактировать 1:
На вопрос ...
, почему он работает с moveToThread ()?
Рассмотрим реализацию MainWidget
ctor ...
MainWidget()
{
worker = new Worker;
worker->moveToThread(&thread);
connect(this, &MainWidget::start, worker, &Worker::run);
thread.start();
emit start();
}
К моменту вызова Worker::run
экземпляр Worker
был перемещен в новый поток. Таким образом, когда строка ...
timer.start(1000, this);
выполняется, this
(что относится к экземпляру Worker
) находится в текущем потоке, и тест сходства потока в QBasicTimer::start
проходит без предупреждения.
Извините, если вышесказанное немного запутано, но важно учитывать близость потока второго аргумента к QBasicTimer::start
: он должен быть текущим запущенным потоком.