Runnning (C++) function in background
-
Is there a document / tutorial explaining and tying all of these together ?
They are documented individually and there are plenty of code examples too.QFuture
QFutureWatcher
QSignalSpy
QPromise
QtConcurrentMy objective is to run time consuming function in background , but I like to have more than “ elapsed time “ indicator in main program – the background function reports on its progress / state while running.
I found QProgressDialog example but that has only timing SIGNAL as "progress indicator ". (And the example is not that well documented )
I am NOT asking for code - I have that covered.
Thanks
. -
Is there a document / tutorial explaining and tying all of these together ?
They are documented individually and there are plenty of code examples too.QFuture
QFutureWatcher
QSignalSpy
QPromise
QtConcurrentMy objective is to run time consuming function in background , but I like to have more than “ elapsed time “ indicator in main program – the background function reports on its progress / state while running.
I found QProgressDialog example but that has only timing SIGNAL as "progress indicator ". (And the example is not that well documented )
I am NOT asking for code - I have that covered.
Thanks
.@AnneRanch said in Runnning (C++) function in background:
I found QProgressDialog example but that has only timing SIGNAL as "progress indicator ". (And the example is not that well documented )
Simply make your own signal and pass whatever information/data you want that way, it must not necessarily be an integer that represents progress; you could use your own class/struct.
-
Is there a document / tutorial explaining and tying all of these together ?
They are documented individually and there are plenty of code examples too.QFuture
QFutureWatcher
QSignalSpy
QPromise
QtConcurrentMy objective is to run time consuming function in background , but I like to have more than “ elapsed time “ indicator in main program – the background function reports on its progress / state while running.
I found QProgressDialog example but that has only timing SIGNAL as "progress indicator ". (And the example is not that well documented )
I am NOT asking for code - I have that covered.
Thanks
.@AnneRanch
To report on background/thread state, so that foreground UI can show something, you do not need any of these (except the generic QtConcurrent for thread running). Just like withQProgressDialog
, all you need is to have your background thread emit a signal, with some suitable parameters in it, when it feels like it has "something to say" (e.g. finished some calculation or received/generated some data), which the foreground has a slot on and reports.The others, like
QFuture
/QPromise
, are to do with with recognising when the threads finish, and return a result. But you want "progress notifications" while the background is running, don't you? -
@AnneRanch
To report on background/thread state, so that foreground UI can show something, you do not need any of these (except the generic QtConcurrent for thread running). Just like withQProgressDialog
, all you need is to have your background thread emit a signal, with some suitable parameters in it, when it feels like it has "something to say" (e.g. finished some calculation or received/generated some data), which the foreground has a slot on and reports.The others, like
QFuture
/QPromise
, are to do with with recognising when the threads finish, and return a result. But you want "progress notifications" while the background is running, don't you?@JonB Yes, I want background emitting SIGNAL which I can process in main thread . ( I think I need just timing intervals for now)
I am having difficult time understanding the
ability of QConcurrent :: run to do so .Most documentation say it cannot monitor the background but
this combination can :futureWatcher.setFuture(QtConcurrent::map(vector, spin));
then some use QConcurrent :: run and claim it can monitor the background.
The odd part , IMHO, is that there is no real example code simply shoving the background ( QPropgressDialog) and the main running same time.
( I am working on that one)The closest example I found was based on modal /modeleess dialog.
Just to confuse me more. -
You can add custom signals to the method you call in QtConcurrent::run to report the progress however you like. Because the other QtConcurrent methods (map, mapped, etc.) apply a function to each item in a container, there is an intuitive way to think about and report the progress; when it has run on a quarter of the objects in the container; its progress is 25%. With QtConcurrent::run, it just runs an arbitrary method in a separate thread and without adding your own logic inside that method, there's no intuitive, universal way to report its progress.
-
You can add custom signals to the method you call in QtConcurrent::run to report the progress however you like. Because the other QtConcurrent methods (map, mapped, etc.) apply a function to each item in a container, there is an intuitive way to think about and report the progress; when it has run on a quarter of the objects in the container; its progress is 25%. With QtConcurrent::run, it just runs an arbitrary method in a separate thread and without adding your own logic inside that method, there's no intuitive, universal way to report its progress.
@mchinand It seems simple , but ...I call "system(command)" : which is thread blocking , irregardless if main or "concurrent".
In simplest terms I need two loops
timer loop (main thread)
{
system call loop (concurrent thread)
{
}
}
the concurrent thread cannot provide any SIGNAL except completion...
Then the timer loop can guess if the "system" provided correct data by checking expected time for correct completion
and of course it will fully validate the "system" call by checking the data file . -
@mchinand It seems simple , but ...I call "system(command)" : which is thread blocking , irregardless if main or "concurrent".
In simplest terms I need two loops
timer loop (main thread)
{
system call loop (concurrent thread)
{
}
}
the concurrent thread cannot provide any SIGNAL except completion...
Then the timer loop can guess if the "system" provided correct data by checking expected time for correct completion
and of course it will fully validate the "system" call by checking the data file .@AnneRanch
What does "system call loop" mean/do?- If it's a loop you can
emit someSignal()
each time round the loop, like:
for (int i = 0; i < 10; i++) { doSomeOneAction(); emit someSignal(); }
- If it actually issues a runtime library
system()
call, you cannot do anything in the thread during thesystem()
call --- as that blocks the thread it is run from, which we have discussed previously --- only before or after.
- If it's a loop you can
-
For one, the QProgressDialog does not run in the background (at least I wouldn't call it that). The QProgressDialog has to run in the main thread, the GUI thread. This is the thread which is there by default. The other thread, that does the heavy lifting, is usually called worker thread. Just making sure you got it right, where to place the QProgressDialog.
If you are using QtConcurrent::run there are two ways to talk to the progress dialog: First, there is signals and slots. This requires that you have an object which can actually emit signals (and that signal needs to be connected to the slot of the QProgressDialog somehow). Most of the time I don't necessarily have an existing object (or class derived from QObject). In that case I just use
QMetaObject::invokeMethod(qApp(), [progressDialog,progress]() { progressDialog->setValue(progress); })
. This will put a slot call into the GUI's event loop. The advantage is that you don't need an explicit signal to trigger the call to the slot. I usually use lambdas in this context. The exact syntax/captured variables need to be adapted to your actual use case. Most important: make sure that you don't have to many successive calls to update the progress as this can significantly slow down your actual computation. -
For one, the QProgressDialog does not run in the background (at least I wouldn't call it that). The QProgressDialog has to run in the main thread, the GUI thread. This is the thread which is there by default. The other thread, that does the heavy lifting, is usually called worker thread. Just making sure you got it right, where to place the QProgressDialog.
If you are using QtConcurrent::run there are two ways to talk to the progress dialog: First, there is signals and slots. This requires that you have an object which can actually emit signals (and that signal needs to be connected to the slot of the QProgressDialog somehow). Most of the time I don't necessarily have an existing object (or class derived from QObject). In that case I just use
QMetaObject::invokeMethod(qApp(), [progressDialog,progress]() { progressDialog->setValue(progress); })
. This will put a slot call into the GUI's event loop. The advantage is that you don't need an explicit signal to trigger the call to the slot. I usually use lambdas in this context. The exact syntax/captured variables need to be adapted to your actual use case. Most important: make sure that you don't have to many successive calls to update the progress as this can significantly slow down your actual computation.@SimonSchroeder said in Runnning (C++) function in background:
In that case I just use QMetaObject::invokeMethod(qApp(), progressDialog,progress { progressDialog->setValue(progress); })
If you're going to use
invokeMethod
you might as well not pass it unnecessarily through the application object - you already have the correct context object.QMetaObject::invokeMethod(progressDialog, std::bind(&QProgressDialog::setValue, progressDialog, progress));
You could alternatively post a custom event to the dialog with
QCoreApplication::postEvent
.