QThreads, QObject and sleep function

The problem I ran into is that I decided to implement QThreads way they should, based on numerous articles:
http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

and the problem is that since the algorithm runs in a separate QObject (wrapped in QThread ). how can i call something like Thread::Sleep or smth .. Any ideas?

A small description of the software. Basically my application solves TSP (seller problem). As the search progresses, the search saves all states in history as frames .. (for example, visual frames). Search algorithms will be executed in one thread. The main thread controls the graphical interface. Then there is a Mediaplayer like stream that tells the Main stream which frame will be displayed on the screen. So where does the dream come in? Gui has a slider that the user can use to fast forward or at a normal pace. This slider reports through the signal slot in the Mediaplayer stream to go faster or slower.

+8
c ++ qt qthread
source share
3 answers

What we did was basically something like this: (written by memory, since I do not have our code extracted on this computer)

 class Sleeper : public QThread { public: void sleep(int ms) { QThread::sleep(ms); } }; void sleep(int ms); // in a .cpp file: static Sleeper slp; void sleep(int ms) { slp.sleep(ms); } 

The key is that the QThread::sleep function causes the calling thread to sleep, not the threaf represented by the QThread instance. So just create a wrapper that calls it through a custom subclass of QThread .

Unfortunately, QThread is a mess. The documentation states that you are using it incorrectly. A few blog posts, as you already said, tell you better about this, but then you cannot call functions like sleep , which should never have been a protected thread element.

And most importantly, even regardless of how you use QThread, it is designed to emulate what is probably the worst API ever created, Java. Compared to something sensible, like boost::thread or even better, std::thread , it is bloated, harder and more useless to use, and requires a staggering amount of template code.

This is truly one of the places where the Qt team blew it up. Big time.

+6
source share

The simple answer is: you should not block the asynchronous start code with completion - each event handler and slot implementation in QObject should do its job and return as soon as possible. He should not do any lively or sleeping. For more information on this line, see Miro Samek. I do not like RTOS files .

For a more efficient implementation, which follows from the above, see instead . The macro that follows is best left to poor souls stuck with C.

I have attached an example of how to do this correctly, at least in terms of what the code does. If you want to do a real implementation, look no further than Boost uncouch coroutines .

Macro addition - syntactic sugar - this makes the technique more acceptable (Boost does it better than I do below). Whether you use macros or write methods explicitly is up to you. The syntax is not what is claimed to be the "right way." I am not the only one who uses such a preprocessor blende . There is no support for nested function calls and several "threads" to complete execution until completion in QObject . This example shows the code for only one "thread" and only one level of calls to the asynchronous call function. Stackless Python brings this to its logical conclusion.

You will see this template in all your code if you write it in an asynchronous way. The SLEEP macro is syntactic sugar that helps make code simpler. There is no truly clean way to write it without a hacker macro in C ++, where the syntax will not be overbearing. Even with C ++ 11, the language does not have built-in output support. See Why in C ++ 0x? no revenue has been added.

This is really non-blocking code, you will see that the periodic timer event fires while you are "sleeping". Note that this collaborative multitasking has much lower overhead than threads / processes performed by the OS. There was a reason that the 16-bit code of a Windows application was written as follows: it works pretty well even on meager equipment.

Note that QThread not needed for this code, and in fact, it does not use QThread , although if you move the object to a thread with a high priority, the delays will have a lower spread.

The implementation of the Qt timer is smart enough to reduce the timer period on Windows if the period is "short." You can use the platform-specific code, which I will show below, but this should be discouraged. On Qt 5, you simply start the Qt::PreciseTimer . Note that on systems prior to Windows 8, you trade on power consumption and are slightly higher than kernel overhead for performance here. Windows 8, OS X (xnu), and modern Linux are carefree and do not suffer from such performance degradation.

I must admit the clear direction of preprocessor abuse from creating the C # C ## and __LINE__ macros (combining markers using a positioning macro) .

Similar to the SLEEP() macro, you can also implement the GOTO() macro to allow you to have simple machines with an end state that are written in the style of a simple lock code, but are still asynchronous behind the scenes. You can have the ENTER() and LEAVE() macros to implement the actions that must be performed when entering and exiting the state, etc., But the code may look completely like a direct encoding function with locking. I found it quite productive and lighter than code that lacks syntactic sugar coverage. YMMV. In the end, you will have something that is on the way to UML state maps, but at a lower cost (both at runtime and in text) than QStateMachine-based .

Below is the conclusion, stars are periodic ticks.

 doing something * * * * * * * * * * slept, a=10 * * * * * slept, a=20 * * slept, a=30 * slept, a=40 
 #sleep.pro QT += core QT -= gui TARGET = sleep CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp 
 //main.cpp #ifdef Q_WS_WIN #include <windows.h> #endif #include <cstdio> #include <QtCore/QTextStream> #include <QtCore/QObject> #include <QtCore/QBasicTimer> #include <QtCore/QTimer> #include <QtCore/QCoreApplication> QTextStream out(stdout); // this order is important #define TOKENPASTE2(x,y) x ## y #define TOKENPASTE(x,y) TOKENPASTE2(x,y) #define SLEEP(ms) sleep(ms, &SLEEPCLASS::TOKENPASTE(fun, __LINE__)); } void TOKENPASTE(fun, __LINE__)() { class Object : public QObject { Q_OBJECT #define SLEEPCLASS Object // used by the SLEEP macro public: Object() { QTimer::singleShot(0, this, SLOT(slot1())); periodic.start(100); connect(&periodic, SIGNAL(timeout()), SLOT(tick())); } protected slots: void slot1() { a = 10; // use member variables, not locals out << "doing something" << endl; sleep(1000, &Object::fun1); } void tick() { out << "*" << endl; } protected: void fun1() { out << "slept, a=" << a << endl; a = 20; SLEEP(500); out << "slept, a=" << a << endl; a = 30; SLEEP(250); out << "slept, a=" << a << endl; a = 40; SLEEP(100); out << "slept, a=" << a << endl; qApp->exit(); } private: int a; // used in place of automatic variables private: void sleep(int ms, void (Object::*target)()) { next = target; timer.start(ms, this); } void timerEvent(QTimerEvent * ev) { if (ev->timerId() == timer.timerId()) { timer.stop(); (this->*next)(); } } QTimer periodic; QBasicTimer timer; void (Object::* next)(); }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Object o1; #ifdef Q_WS_WIN timeBeginPeriod(1); // timers will be accurate to 1ms #endif return a.exec(); } #include "main.moc" 
+4
source share

I agree with jalf. I have a thread that acts as a kind of DBUS daemon and should listen to messages forever. Two things to mention:

jalf has

 void sleep(int ms) { QThread::sleep(ms); } 

But these are NOT MILLIONSIONS! QThread :: sleep () takes seconds. Also, if someone takes this approach, they should also include QThread lib anyway, so it would be easier to just make a call like this:

 QThread::sleep(seconds); 

directly in the code. Thus, there is no additional header file. I ran this and it also works as jalf explained. (putting the calling thread to sleep).

+2
source share

All Articles