main and background thread example
-
i'll try using
QTimer
instead ofthis_thread::sleep_for()
. but it still blows my mind how my previous implementation worked the way i wanted with this code.and is everything else okay with this code (i.e. the use of atomic bool etc.)?
-
i can't figure out how to do that. this is what i have right now:
#include <QtWidgets/QMainWindow> #include <QApplication> #include <QObject> #include <QThread> #include <iostream> #include <thread> #include <QtWidgets/QLabel> #include <atomic> #include <QTimer> std::atomic<bool> bMainThreadRunning { true }; class ThreadObj : public QObject { public: ThreadObj() : counter(0) {} void work() { auto timer = new QTimer; //timer.setInterval(3000); connect(timer, &QTimer::timeout, this, &ThreadObj::inc); timer->start(3000); } void inc() { while(bMainThreadRunning) ++counter; } private: int counter { 0 }; }; class Obj { public: void start() { ThreadObj obj; m_thread = std::thread(&ThreadObj::work, &obj); } void onMainThreadFinished() { bMainThreadRunning = false; m_thread.join(); } private: std::thread m_thread; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Obj o; o.start(); QWidget w; w.show(); auto ret = a.exec(); o.onMainThreadFinished(); return 0; }
-
i did that. what i need is, when in background thread something weird happens, i tell the main thread to show a message box. then if at some time the "good" state of background thread is restored, main thread closes the message box.
here's what i have now. actually the application works. but at some points it crashes. looking at the crash log i can say that the reason is the background thread but i don't see how my implementation is wrong. i appended the crash log after code.
class BgThread : public QThread { Q_OBJECT public: explicit BgThread (const int &nSeconds, QObject *parent = nullptr) : QThread(parent), interval(1000 * nSeconds) /* to milliseconds */ {} void onStopBgThread() { running = false; } signals: void somethingWentWrong(); void restoreGoodState(); private slots: void performWork() { if(/* something went wrong */) { emit somethingWentWrong(); good_state = false; } else if(!good_state) { // means going from bad state to good state emit restoreGoodState(); good_state = true; } } private: void run() override { QTimer timer; connect(&timer, SIGNAL(timeout()), this, SLOT(performWork()), Qt::DirectConnection); timer.start(interval); exec(); quit(); wait(); } private: int interval; bool running { true }; bool good_state { true }; }; class MainApp { public: void start_bg_thread(const int seconds) { thread = new BgThread { seconds, this }; connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); connect(thread, SIGNAL(somethingWentWrong()), SLOT(onSomethingWentWrong())); connect(thread, SIGNAL(restoreGoodState()), SLOT(onRestoreGoodState())); thread->start(); } void stop_bg_thread() { thread->onStopBgThread(); } public slots: void onSomethingWentWrong() { if(!msgBox) { msgBox= new QMessageBox(window()); msgBox->setIcon(QMessageBox::Warning); msgBox->setWindowTitle("window title"); msgBox->setText("message box text"); const auto pExitBtn = msgBox->addButton(tr("Exit"), QMessageBox::AcceptRole); connect(pExitBtn, SIGNAL(clicked()), qApp, SLOT(quit())); } msgBox->exec(); } void onRestoreGoodState() { msgBox->close(); } private: BgThread *thread { nullptr }; QMessageBox *msgBox; };
this is basically it. and somewhere in the app init process i call
MainApp app; app.start_bg_thread(5);
the crash log is something like this (stacktrace):
do_system () from /lib64/libc.so.6 system () from /lib64/libc.so.6 // call signal handler ... pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 QThread::msleep(unsigned long) () start_thread () from /lib64/libpthread.so.0 clone () from /lib64/libc.so.6 waitpid () from /lib64/libc.so.6 do_system () from /lib64/libc.so.6 system () from /lib64/libc.so.6 // call signal handler BgThread::onStopBgThread () MainApp::qt_metacall(QMetaObject::Call, int, void**) () QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () QCoreApplication::exec() main ()
-
Did you check the memory used by you application ?
-
what do you mean by check? and no, how should i?
-
Using the top command for example. Valgrind etc.
-
okay, thanks.
one last question, as you can see, on timer's timeout i execute a function. is it possible stop the timer (so the function won't be executed), and then restart it again? -
-
hi again,
i ran valgrind and it says there's a memory leak onexec()
which is inrun()
overridden method. so what's wrong? -
i wanna write a basic thread example. here's the idea:
i have the main event loop. before callingapp.exec()
, i create an object which itself creates an object and puts it in a separate thread for running. i need some way to tell the background thread that main thread has finished (tojoin()
), so i have abool
to indicate that.however, when the application exits, something goes wrong. i'm running it using visual studio and the debugging session won't stop. i don't understand what's wrong. here's the code:
#include <QApplication> #include <QObject> #include <QThread> #include <iostream> #include <thread> #include <QtWidgets/QLabel> #include <atomic> std::atomic<bool> bMainThreadRunning { true }; class ThreadObj { public: void work() { while(bMainThreadRunning) { ++counter; std::this_thread::sleep_for(std::chrono::seconds(5)); } } private: int counter { 0 }; }; class Obj { public: void start() { ThreadObj obj; m_thread = std::thread(&ThreadObj::work, &obj); } void onMainThreadFinished() { bMainThreadRunning = true; m_thread.join(); } private: std::thread m_thread; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Obj o; o.start(); QWidget w; w.show(); auto ret = a.exec(); o.onMainThreadFinished(); return 0; }
@user4592357 said in main and background thread example:
ThreadObj obj;
m_thread = std::thread(&ThreadObj::work, &obj);obj is allocated on the stack, it will go out of scope and delete itself
-
@user4592357 said in main and background thread example:
ThreadObj obj;
m_thread = std::thread(&ThreadObj::work, &obj);obj is allocated on the stack, it will go out of scope and delete itself
hi, thanks for the reply.
the code has been modified since the first post (see my last code-post), so it's not the problem -
i've read similar articles, saying "you shouldn't subclass
QThread
". in my case i need to do that. -
Out of curiosity, what are you doing that requires to subclass QThread ?
-
nothing requires it. it's just that the whole implementation is done and i don't wanna change everything