This is objectA which subclass QThread
void run()
{
while (continue)
emit query();
}
void work(int input, bool workdone)
{
// work hard here
if (workdone) { continue = false; }
}
This is some code in main object
{
ObjectA A* = new ObjectA(this);
connect(A, SIGNAL(query()), this, SLOT(handleQuery()));
objectA.start();
}
void handleQuery()
{
A.work(interger, allJobDONE);
}
OK, I don't know how to name the question. Basically, it is just "will this code work?" If yes, how would be the code sequence?
Let me explain my question. ObjectA is a thread. It is going to query information from time to time by emitting a query signal. When the query signal is grubbed by the main code, the main code decide whether there is job so as to send the job to ObjectA by calling work() function.
If this code works, both the run() and the work() function in the same object work at the same time. Is this possible?
There are few problems:
the function ObjectA::run() blocks the event loop of the thread;
A.work() is called from the wrong thread;
it is needed to think about proper deletion of A.
Instead of blocking while loop in run() it is better to use timer. However, in that case the thread event loop should be executed (that it done in the default implementation of QThread::run(). So some other member slot should be used for that task to start, for example:
void ObjectA::doLoop()
{
emit query();
QTimer::singleShot(0, this, SLOT(doLoop()));
}
That function should be called when the thread is started, for example it can be done by connection in ObjectA constructor:
connect(this, SIGNAL(started()), this, SLOT(doLoop()));
Even better to keep private pointer QTimer* to be able to stop that timer from work() or to have some other control. Note that in that case QTimer object should be in the same thread as ObjectA.
Normally the ObjectA::work() function should be triggerd by some signal from handleQuery(). The event loop of ObjectA will catch that signal and the work() will be started in ObjectA thread.
Related
I have the following program, where I am using java.util.concurrent.CountDownLatch and without using await() method it's working fine.
I am new to concurrency and want to know the purpose of await(). In CyclicBarrier I can understand why await() is needed, but why in CountDownLatch?
Class CountDownLatchSimple:
public static void main(String args[]) {
CountDownLatch latch = new CountDownLatch(3);
Thread one = new Thread(new Runner(latch),"one");
Thread two = new Thread(new Runner(latch), "two");
Thread three = new Thread(new Runner(latch), "three");
// Starting all the threads
one.start(); two.start(); three.start();
}
Class Runner implements Runnable:
CountDownLatch latch;
public Runner(CountDownLatch latch) {
this.latch = latch;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+" is Waiting.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
System.out.println(Thread.currentThread().getName()+" is Completed.");
}
OUTPUT
two is Waiting.
three is Waiting.
one is Waiting.
one is Completed.
two is Completed.
three is Completed.
CountDownLatch is the synchronization primitive which is used to wait for all threads completing some action.
Each of the thread is supposed to mark the work done by calling countDown() method. The one who waits for the action to be completed should call await() method. This will wait indefinitely until all threads mark the work as processed, by calling the countDown(). The main thread can then continue by processing the worker's results for example.
So in your example it would make sense to call await() at the end of main() method:
latch.await();
Note: there are many other use cases of course, they don't need to be threads but whatever that runs usually asynchronously, the same latch can be decremented several times by the same task etc. The above describes just one common use case for CountDownLatch.
class Driver : Public QObject
{
Q_OBJECT
private:
// method command: sends a command
// signal ok: command executed, sends back a message
MyDevice *device;
public:
Deriver()
{
device = new MyDevice(0);
connect (mydevice,&MyDevice::ok,this,&Driver::onInitOk);
}
public slots:
void init()
{
device->command("init");
//at this point, I want to block this method until the device signals ok with a given msg
}
command()
{
device->command("setmode x");
device->command("cmd");
//at this point, I want to block this method until the device signals ok with a given msg
}
void onInitOk(QString msg)
{
//somehow unblock the actually running command, if the msg matches
}
}
I would like to use the command/init with a QueuedConnection, so they are executed async from the gui thread, and sequentially. (Am I right?)
How can I implement the blocking effectively?
Okay so I've edited based on the clarity of the comments given. The best place to look at would be the Qt Threading Guide. This can give a much better breakdown on the systems used for concurrency.
For your example I've added a QMutex object to your Driver class. It may be worth thinking about if you want to move the thread-based controls into the MyDevice class itself if you have access.
Driver()
{
moveToThread(new QThread());
device = new MyDevice(0);
}
void init()
{
mutex.lock();
const QString& result = device->command("init");
onInitOk(result);
}
void command()
{
mutex.lock();
device->command("setmode x");
const QString& result = device->command("cmd");
onInitOk(result);
}
void onInitOk(QString msg)
{
...[STUFF]
// Even when things go wrong you MUST unlock the mutex at some point.
// You can't keep the thread blocked forever in cases of poor results.
// As such it might be better practice to unlock in
// the same function that locks!
mutex.unlock();
}
QMutex mutex;
Bear in mind I am assuming you are wanting to access the functionality from the slots mechanism. Hence why we use the moveToThead() function. When the object is accessed via slots in the GUI thread it'll now run the function on a different thread.
Likewise the mutex only blocks for all the objects that share that one mutex instance. So depending on your implementation you may have to think about what is right for you in exposing that mutex.
I work in Qt and when I press the button GO I need to continuously send packages to the network and modify the interface with the information I receive.
The problem is that I have a while(1) in the button so the button never finishes so the interface is never updated. I thought to create a thread in the button and put the while(){} code there.
My question is how can I modify the interface from the thread? (For example how can I modify a textBox from the thread ?
Important thing about Qt is that you must work with Qt GUI only from GUI thread, that is main thread.
That's why the proper way to do this is to notify main thread from worker, and the code in main thread will actually update text box, progress bar or something else.
The best way to do this, I think, is use QThread instead of posix thread, and use Qt signals for communicating between threads. This will be your worker, a replacer of thread_func:
class WorkerThread : public QThread {
void run() {
while(1) {
// ... hard work
// Now want to notify main thread:
emit progressChanged("Some info");
}
}
// Define signal:
signals:
void progressChanged(QString info);
};
In your widget, define a slot with same prototype as signal in .h:
class MyWidget : public QWidget {
// Your gui code
// Define slot:
public slots:
void onProgressChanged(QString info);
};
In .cpp implement this function:
void MyWidget::onProgressChanged(QString info) {
// Processing code
textBox->setText("Latest info: " + info);
}
Now in that place where you want to spawn a thread (on button click):
void MyWidget::startWorkInAThread() {
// Create an instance of your woker
WorkerThread *workerThread = new WorkerThread;
// Connect our signal and slot
connect(workerThread, SIGNAL(progressChanged(QString)),
SLOT(onProgressChanged(QString)));
// Setup callback for cleanup when it finishes
connect(workerThread, SIGNAL(finished()),
workerThread, SLOT(deleteLater()));
// Run, Forest, run!
workerThread->start(); // This invokes WorkerThread::run in a new thread
}
After you connect signal and slot, emiting slot with emit progressChanged(...) in worker thread will send message to main thread and main thread will call the slot that is connected to that signal, onProgressChanged here.
P.s. I haven't tested the code yet so feel free to suggest an edit if I'm wrong somewhere
So the mechanism is that you cannot modify widgets from inside of a thread otherwise the application will crash with errors like:
QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
Segmentation fault
To get around this, you need to encapsulate the threaded work in a class, like:
class RunThread:public QThread{
Q_OBJECT
public:
void run();
signals:
void resultReady(QString Input);
};
Where run() contains all the work you want to do.
In your parent class you will have a calling function generating data and a QT widget updating function:
class DevTab:public QWidget{
public:
void ThreadedRunCommand();
void DisplayData(QString Input);
...
}
Then to call into the thread you'll connect some slots, this
void DevTab::ThreadedRunCommand(){
RunThread *workerThread = new RunThread();
connect(workerThread, &RunThread::resultReady, this, &DevTab::UpdateScreen);
connect(workerThread, &RunThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
The connection function takes 4 parameters, parameter 1 is cause class, parameter 2 is signal within that class. Parameter 3 is class of callback function, parameter 4 is callback function within the class.
Then you'd have a function in your child thread to generate data:
void RunThread::run(){
QString Output="Hello world";
while(1){
emit resultReady(Output);
sleep(5);
}
}
Then you'd have a callback in your parent function to update the widget:
void DevTab::UpdateScreen(QString Input){
DevTab::OutputLogs->append(Input);
}
Then when you run it, the widget in the parent will update each time the emit macro is called in the thread. If the connect functions are configured properly, it will automatically take the parameter emitted, and stash it into the input parameter of your callback function.
How this works:
We initialise the class
We setup the slots to handle what happens with the thread finishes and what to do with the "returned" aka emitted data because we can't return data from a thread in the usual way
we then we run the thread with a ->start() call (which is hard coded into QThread), and QT looks for the hard coded name .run() memberfunction in the class
Each time the emit resultReady macro is called in the child thread, it's stashed the QString data into some shared data area stuck in limbo between threads
QT detects that resultReady has triggered and it signals your function, UpdateScreen(QString ) to accept the QString emitted from run() as an actual function parameter in the parent thread.
This repeats every time the emit keyword is triggered.
Essentially the connect() functions are an interface between the child and parent threads so that data can travel back and forth.
Note: resultReady() does not need to be defined. Think of it as like a macro existing within QT internals.
you can use invokeMethod() or Signals and slots mechanism ,Basically there are lot of examples like how to emit a signal and how to receive that in a SLOT .But ,InvokeMethod seems interesting .
Below is example ,where it shows How to change the text of a label from a thread:
//file1.cpp
QObject *obj = NULL; //global
QLabel *label = new QLabel("test");
obj = label; //Keep this as global and assign this once in constructor.
Next in your WorkerThread you can do as below:
//file2.cpp (ie.,thread)
extern QObject *obj;
void workerThread::run()
{
for(int i = 0; i<10 ;i++
{
QMetaObject::invokeMethod(obj, "setText",
Q_ARG(QString,QString::number(i)));
}
emit finished();
}
you start thread passing some pointer to thread function (in posix the thread function have the signature void* (thread_func)(void*), something equal under windows too) - and you are completely free to send the pointer to your own data (struct or something) and use this from the thread function (casting pointer to proper type). well, memory management should be though out (so you neither leak memory nor use already freed memory from the thread), but this is a different issue
UpdateThread is-a QThread That sets up a QTimer in UpdateThread::run() that calls slot UpdateThread::tick() every t ms. Now based upon some condition I need to Pause the Thread and after some time based upon another condition I need to wake it up.
Is the Way I am doing the QTimer thing is Okay ? or I should move the tick code to run and call the QThread::start() every t ms ?
How can I Pause and wake up the threads conditionally
Or I should just stop() the QTimer and start() it latter ?
First of all, you shouldn't define slots on your QThread subclass and call them from within run() - the slots will be executed (by performing a cross-thread slot invocation) in the context of the thread that owns your UpdateThread instance (the same one that created it, unless you called moveToThread() on it), not in the context of the thread represented by UpdateThread. Remember this mnemonic:
In run(), QThread::thread() != this
Instead, define the slots on a QObject subclass that you create inside run().
Ok, with that out of the way, let's have a look at the timer. The QTimer documentation contains the following:
In multithreaded applications, you can use QTimer in any thread that has an event loop.
To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's
thread affinity to determine which thread will emit the timeout() signal.
Because of this, you must start and stop the timer in its thread; it is not possible to
start a timer from another thread.
(emphasis mine) Take particular note of the last sentence.
The solution is to do a cross-thread call of QTimer::start() and QTimer::stop(). You might know about cross-thread signal/slot connections. This uses the same underlying mechanism, which is exposed in QMetaObject::invokeMethod():
class UpdateThread : public QThread {
Q_OBJECT
private:
QObject * m_timer; // just a QObject* so we're not tempted
// to call functions on it
QMutext m_mutex; // protects 'm_timer'
public:
explicit UpdateThread( QObject * parent=0 )
: QThread( parent ), m_timer( 0 ) {}
// ...
private:
/* reimpl */ void run() {
QTimer timer;
// ...'timer' setup code goes here...
{
const QMutexLocker locker( &m_mutex );
m_timer = &timer; // publish 'timer' through 'm_timer'
}
// main code of run()
exec(); // start event loop so we get timer's timeout()s
// and we can receive cross-thread method calls
{
const QMutexLocker locker( &m_mutex );
m_timer = 0; // un-publish before we delete `timer`
}
}
public Q_SLOTS:
void startTimer() {
const QMutexLocker locker( &m_mutex );
if ( !m_timer ) return;
// perform cross-thread method call:
QMetaObject::invokeMethod( m_timer, "start", Qt::QueuedConnection );
}
void stopTimer() {
const QMutexLocker locker( &m_mutex );
if ( !m_timer ) return;
// perform cross-thread method call:
QMetaObject::invokeMethod( m_timer, "stop", Qt::QueuedConnection );
}
};
Now, this is how you start/stop the timer from the GUI thread. But you were also asking about alternatives.
Move tick() code into run(), call UpdateThread::start() every t milliseconds.
This is suboptimal, as it would create and destroy threads every t ms. Thread creation is still an expensive operation. Also, if UpdateThread::run() isn't done by the time you next call start(), you'll lose timer ticks.
UpdateThread as outlined above.
This isn't too bad, but it's not idiomatic multithreading, I'd say. It's a good solution if the timer fires so often that that alone would slow down the GUI thread somehow, though you might lose timer ticks this way, too.
QThreadPool
My favourite. Move the code that performs tick() into an implementation of QRunnable::run(), and queue a new runnable on a thread pool whenever the timer fires. In this case, the timer would most naturally live in the GUI thread, avoiding the need for cross-thead method calls as outlined above. Unless the GUI thread itself is overloaded, you won't miss any timer ticks. You also get for free scaling to the number of cores in the system (if you don't want that, don't use QThreadPool::globalInstance() but create your own instance and call setMaxThreadCount(1)).
I have a program which runs a thread. The thread performs processing all the time and it uses some synchronized queue.
The class snapshot is as follows:
public class MyClass:IDisposable
{
private Thread myThread = new Thread(threadFunc);
private volatile bool runThread = true;
public MyClass()
{
myThread.Start();
}
public Dispose()
{
runThread = false;
}
private void threadFunc()
{
try
{
while(runThread){
queue.Take(); //This method blocks the thread if queue is empty. It uses Monitor class
//do some processing
}
}
catch(Exception e){...}
}
private void otherFunc()
{
queue.enqueue(...);//this method is executed by main thread and uses lock while adding element to the queue.
}
}
When I call Dispose() method, the thread exists threadFunc() method, but after a sec I get an execption from this func "Unable to avaluate expression...", as if the tread was terminated while doing some work. Maybe it has just released from queue.Take() blocking and has no context to run. I know I'm missing something...
How can I solve such problem and terminate the thread from the Dispose method.
Many thanks!!!
Use the overload of Take that accepts a CancellationToken. You can get a reference to a token by using the CancellationTokenSource which also has the Cancel method that you can call from Dispose to unblock the Take method. You can read more cancellation here.
Use the poison pill approach: See this thread