Unsolved Software structure question, threads
-
Hallo,
I am building a software which constantly requests a JSON/REST API and then saves the collected data somewhere so that another part of the software can work with it. Execute Systemcommands and so on. This all should happen simultaneously. Also there should be a textfiled which shows some infos about what the software is doing.
So my question is what is the best way to structure this?
I thought about using threads for the rest api reading part and also another thread for the worker part. But now I am stuck what would be the best way to save the data collected via rest. Would you use a database? Or a global array/vector?
When do I have to lock mutex and when not? I hop it got clear what I am trying to ask.Cheers,
Rob -
Hi and welcome to devnet,
For the REST part you can use QNetworkAccessManager. Since it's already working asynchronously you can avoid using a thread for it unless your network activity is heavy enough to slow down the GUI.
As for saving your data, it all depends on what you will do with it, if it must be persistent etc.
You have to use mutex as soon as you have several thread trying to read from and write to a given resource.
Hope it helps
-
Thanks!
I successfully build a working REST request with QNetworkAccessManager and QJsonDocument.
Since it will run in a constant loop and request new infos from time to time maybe a thread is still a good idea to use. I also will do that for the QProcess action i like to implement.
I will have some persistent data which ic maybe can save via the QSettings class. The other Infos will live in an Object/Vector or Array. Did I understand it right that the signal/slot system is thread safe and I dont have to use mutex for it? What about the data which is passed by the signal/slot? For example an array. Can I handle those data without locking? -
Passing data between threads using signal/slot arguments does not need thread synchronization. Using the data may need synchronization. This depends on whether the data is shared between the threads. If all data is copied with pass by value arguments then there is no issue but be careful with deep structures as all levels must be copied. If references or pointers to data are passed as signal/slot arguments then thread synchronization will be required unless you can guarantee that the producing thread makes no further access after the signal is sent.
Nothing you have described so far requires you to create threads in your code. QNetworkAccessManager and the replies it delivers can be used asynchronously with signals and slots, QProcess and the QIODevice objects it gives you to handle the process input, output and error streams can all be used asynchronous using signals and slots. Avoid all use of the wait...() member functions in the main thread. Only if you have CPU intensive work to do in your main thread or if you have to block waiting on some external device do you really need to consider using threads explicitly.
Getting multi-threaded code right is hard and TBH if you are unsure whether it is needed then you probably do not have the skills to implement it correctly.
-
thanks for you explanation. You are right, I am not fully aware how to use QThread the right way. Also I have not much experience with the use of the signal/slot principles. Lets take my QProcess as an example how would i use it asynchronously. For example this code below gives me no output in the console until I use
worker->waitForReadyRead(-1) which is no emiting signal and therefore blocks my loop.
My worker process is quite slow and can take several minutes to finish. I hope you understand what i mean.QProcess *worker = new QProcess(this);
connect(worker, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
worker->start(program, arguments);void MainWindow::readStandardOutput(){
textEdit->insertPlainText (blenderWorker->readAllStandardOutput());
} -
Your code looks fine. Perhaps your process is going wrong and sending output to stderr, if you connect http://doc.qt.io/qt-5/qprocess.html#readyReadStandardError to another slot in your MainWindow class and call readAllStandardError in that slot member function then you will get some answers. Also you need to connect http://doc.qt.io/qt-5/qprocess.html#finished to to a slot so you can capture the exit code of your process and know when it has finished.
I assume:
textEdit->insertPlainText (blenderWorker->readAllStandardOutput());
is an error and you meant:
textEdit->insertPlainText (worker->readAllStandardOutput());
-
Somehow all is fine now. I setup the signal/slot system properly and it seem to work like I wanted.
Am I right when I say that i can use the QTimer functionality in the same way? So that nothing gets blocked?
How awesome would that be :). Thanks for the explanations! -
Yes, QTimer is used to either fire and forget a slot or repeatedly. Note that the time it take to run the slot should be shorter than the timer interval.