Page 1 of 1

Using std::thread to call function at timed intervals?

Posted: Sat Jun 27, 2020 2:50 am
by tuk1
I'm new to std::thread and threading in general, so attempting to get it working at a basic level, ...but, running into some problems.

Objective:
Press a button on UI which triggers the process of calling a Model function 3 times with a 2 second interval between each call.

During this process the rest of the program should be running concurrently( in a separate thread ).


Event handler for the button, which sets up the thread and calls the Model function in question via the controller(MVC).

Code: Select all

void MAIN_FRAME::OnButtonClick_CallModelFuncAtIntervals( wxCommandEvent& WXUNUSED( event ) )
{	
	std::thread t(&MVC::ModelFuncAtIntervals, this->_MVC);	

	t.join();	
}
The controller function contains the timed call loop...

Code: Select all

void MVC::ModelFuncAtIntervals()
{
	for ( int i = 0; i < 3; i++ )
	{
		this->Model->Func();

                std::this_thread::sleep_for(std::chrono::seconds(2));
	}
}
The Model function being called...

Code: Select all

void Model::Func()
{
	My_Diagnostic.log("Refresh!");

       ....Do stuff!
}
We can see from the runtime log the function gets called as expected.
Capture.PNG
Capture.PNG (6.06 KiB) Viewed 471 times
---------

The problem is while this process is running the UI is frozen and unresponsive.

What is required to make this process execute concurrently with the main program?

Re: Using std::thread to call function at timed intervals?

Posted: Sat Jun 27, 2020 6:24 am
by Kvaz1r
join is blocks current thread and waiting for finishing of runned thread.
What does your Model function do? How it's related to UI part and how it's depend on it? (i.e. it possible to call the function again before previous calling was done,...)

Re: Using std::thread to call function at timed intervals?

Posted: Sat Jun 27, 2020 9:42 am
by tuk1
Kvaz1r wrote:
Sat Jun 27, 2020 6:24 am
join is blocks current thread and waiting for finishing of runned thread.
Yes, but putting std::thread to sleep ...should then pass control back to the master/UI thread right?

Code: Select all

std::this_thread::sleep_for(std::chrono::seconds(2));
Kvaz1r wrote:
Sat Jun 27, 2020 6:24 am
What does your Model function do? How it's related to UI part and how it's depend on it? (i.e. it possible to call the function again before previous calling was done,...)
I dont want to wander too far off topic with the details of the Model function, the code example is just a simplified version of the problem(s) that need solving.

...but, lets say the Model function checks a file to see if it has been updated, if so then reloads the file data into a vector ...the contents of the vector is then viewed in the UI. I already use wxTimer to do this but want to use std::thread instead.

Re: Using std::thread to call function at timed intervals?

Posted: Sat Jun 27, 2020 10:17 am
by Kvaz1r
tuk1 wrote:
Sat Jun 27, 2020 9:42 am
Yes, but putting std::thread to sleep ...should then pass control back to the master/UI thread right?
No, not at all. Sleep just block execution of the thread.

tuk1 wrote:
Sat Jun 27, 2020 9:42 am
...but, lets say the Model function checks a file to see if it has been updated, if so then reloads the file data into a vector ...the contents of the vector is then viewed in the UI. I already use wxTimer to do this but want to use std::thread instead.
It's really important part, because UI is not multithreaed. So you should provide some synchronize mechanism for update it time to time.
There is post with example for wxThread using - you can use it as a base - viewtopic.php?f=1&t=46485#p194840
But std::thread is low-level way so maybe better use high-level stuff from standard library like std::future.

Re: Using std::thread to call function at timed intervals?

Posted: Sat Jun 27, 2020 11:23 am
by tuk1
Kvaz1r wrote:
Sat Jun 27, 2020 10:17 am
tuk1 wrote:
Sat Jun 27, 2020 9:42 am
Yes, but putting std::thread to sleep ...should then pass control back to the master/UI thread right?
No, not at all. Sleep just block execution of the thread.
According to the documentation(and seen in various examples) it should do a bit more than just blocking execution of the thread or does it mean other std::threads threads only? ...pertinent part in bold:
std::this_thread::sleep_for

template <class Rep, class Period>
void sleep_for (const chrono::duration<Rep,Period>& rel_time);

Sleep for time span
Blocks execution of the calling thread during the span of time specified by rel_time.

The execution of the current thread is stopped until at least rel_time has passed from now. Other threads continue their execution.
tuk1 wrote:
Sat Jun 27, 2020 9:42 am
...but, lets say the Model function checks a file to see if it has been updated, if so then reloads the file data into a vector ...the contents of the vector is then viewed in the UI. I already use wxTimer to do this but want to use std::thread instead.
It's really important part, because UI is not multithreaed. So you should provide some synchronize mechanism for update it time to time.
There is post with example for wxThread using - you can use it as a base - viewtopic.php?f=1&t=46485#p194840
But std::thread is low-level way so maybe better use high-level stuff from standard library like std::future.
Thanks, it seems I have some reading to do, but at first glance this seems very complicated...why cant I just somehow hand back execution to the main wxthread while std::thread is sleeping!?!? :D

Re: Using std::thread to call function at timed intervals?

Posted: Sat Jun 27, 2020 12:03 pm
by Kvaz1r
tuk1 wrote:
Sat Jun 27, 2020 11:23 am
The execution of the current thread is stopped until at least rel_time has passed from now. Other threads continue their execution.
The bold part means that any other threads are not affected by calling sleep for current one.
tuk1 wrote:
Sat Jun 27, 2020 11:23 am
why cant I just somehow hand back execution to the main wxthread while std::thread is sleeping!?!? :D
Well you can, it's just not task for sleeping. Execution of main thread is not stopping when worker thread execute - it's the aim of multi-threading. If it's not an option there is yield function.
So the main point there is *when* should main thread been blocked (= wait for data from worker thread or worker just finished). It could be hidden in some queue or written explicitly (join for std::thread, get() for std::future).

Re: Using std::thread to call function at timed intervals?

Posted: Mon Jul 20, 2020 5:57 am
by tuk1
Kvaz1r wrote:
Sat Jun 27, 2020 12:03 pm
Thanks, I haven't forgotten about this thread, tbh the learning curve was steep and had to rip out the guts of my project which took some time.

PB's example code on your link was a good, so was able to implement.

I'm not quite there yet and possibly have other std/wx thread related questions, but have run into some issues in the meantime.

viewtopic.php?f=1&t=47358