killTimer: Timers cannot be stopped from another thread
-
@DungeonLords said in killTimer: Timers cannot be stopped from another thread:
tim->start();
Where is tim living (in which thread)? You just have to make sure the timer lives in the thread where it is used. Usually you achieve it by creating it in the thread.
@jsulm askTim located in main thread but it's slot GetTime() is located in worker thread...
-
@jsulm askTim located in main thread but it's slot GetTime() is located in worker thread...
@DungeonLords I asked about tim, not askTim.
Again: where and when is tim created? -
@DungeonLords I asked about tim, not askTim.
Again: where and when is tim created? -
@DungeonLords said in killTimer: Timers cannot be stopped from another thread:
tim is created in Worker thread
Are you sure? Can you please show where exactly you're creating it?
-
@DungeonLords said in killTimer: Timers cannot be stopped from another thread:
tim is created in Worker thread
Are you sure? Can you please show where exactly you're creating it?
void Worker::run() { qDebug() << "Worker::run"; tim= new QTimer(this); //<<here connect(tim, &QTimer::timeout, this, &Worker::timer_clb, static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)); tim->setInterval(400); while(1)
Worker::run() is not a constructor and doesn't call from Worker's constructor. Worker's run() method starts by thread's signal started():
connect(thread.get(), &QThread::started, worker.get(), &Worker::run); thread->start();
-
void Worker::run() { qDebug() << "Worker::run"; tim= new QTimer(this); //<<here connect(tim, &QTimer::timeout, this, &Worker::timer_clb, static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)); tim->setInterval(400); while(1)
Worker::run() is not a constructor and doesn't call from Worker's constructor. Worker's run() method starts by thread's signal started():
connect(thread.get(), &QThread::started, worker.get(), &Worker::run); thread->start();
@DungeonLords said in killTimer: Timers cannot be stopped from another thread:
QTimer(this)
So you create it in the main thread as the QThread object lives in the main thread.
-
void Worker::run() { qDebug() << "Worker::run"; tim= new QTimer(this); //<<here connect(tim, &QTimer::timeout, this, &Worker::timer_clb, static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)); tim->setInterval(400); while(1)
Worker::run() is not a constructor and doesn't call from Worker's constructor. Worker's run() method starts by thread's signal started():
connect(thread.get(), &QThread::started, worker.get(), &Worker::run); thread->start();
@DungeonLords The problem is probably that you use a scoped pointer for the worker, so it is deleted in main thread. Use raw pointer and connect thread finished signal to deletLater() slot of the worker.
-
@DungeonLords The problem is probably that you use a scoped pointer for the worker, so it is deleted in main thread. Use raw pointer and connect thread finished signal to deletLater() slot of the worker.
@jsulm thanks, now works, I tested by this code, log is without problem:
$ ./QThread_QTimer Worker::Worker MainWindow::MainWindow thread->start() parents QObject(0x0) MainClass(0x7fff7673c740) Worker::run ^CWelcome to Signal handled: 2 requestInterruption emit finished() ~Worker() threadIsFinished ~MainWindow()
Should I open bug report about QScopedPointer in multi-thread proj?
P.S. With std::unique_ptr the same problem like with QScopedPointer...
-
@jsulm thanks, now works, I tested by this code, log is without problem:
$ ./QThread_QTimer Worker::Worker MainWindow::MainWindow thread->start() parents QObject(0x0) MainClass(0x7fff7673c740) Worker::run ^CWelcome to Signal handled: 2 requestInterruption emit finished() ~Worker() threadIsFinished ~MainWindow()
Should I open bug report about QScopedPointer in multi-thread proj?
P.S. With std::unique_ptr the same problem like with QScopedPointer...
@DungeonLords said in killTimer: Timers cannot be stopped from another thread:
Should I open bug report about QScopedPointer in multi-thread proj?
There is no bug.
It's not the job of the QScopedPointer to know in which thread the object lives which it is managing.
The correct way in Qt to delete objects living in other threads is to use deleteLater(). -
-
void Worker::run() { qDebug() << "Worker::run"; tim= new QTimer(this); //<<here connect(tim, &QTimer::timeout, this, &Worker::timer_clb, static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)); tim->setInterval(400); while(1)
Worker::run() is not a constructor and doesn't call from Worker's constructor. Worker's run() method starts by thread's signal started():
connect(thread.get(), &QThread::started, worker.get(), &Worker::run); thread->start();
@DungeonLords said in killTimer: Timers cannot be stopped from another thread:
void Worker::run()
processEvents()
in an infinite loop is not the best solution here. This will produce code that will use a single core a 100%. People will start asking questions why your app is using 100% of one core while it is doing nothing (I'm speaking from experience). The proper solution is to callexec()
instead. However, this is also already the default implementation ofQThread::run()
. So, you can just leverage that and throw away your entire while-loop. Maybe then don't call your methodrun()
but justcreateTimer()
. Then it makes a lot more sense to callconnect(thread.get(), &QThread::started, worker.get(), &Worker::createTimer());
, i.e.createTimer
whenthread
isstarted
. (Instead of usingrequestInterruption
you would then just callquit
.)The use of
exit_LABEL
shows some lack of understanding of asynchronous programming, which is the natural way in Qt. Send signals connected to slots instead to perform such operations. Just out of curiosity: Was AI heavily involved in creating this code? Or are you just coming from embedded systems programming?emit GetTimeAsk();
does not make sense.emit
is usually used for signals only (it compiles because it is replaced by nothing by the preprocessor). Effectively you are just executing a normal member function. This also means that this is just executed in the main thread. (Which in turn means that incrementingi
is not thread safe.)