Modifying global variables from threaded functions and still run the main thread to use the Global varibales - multithreading

I have a project in Visual C++ 2010 where I have to draw some circles and lines. The coordinates of the circles depend on two global variables. The global variables are modified from two functions, each running in their own thread. Boost is used for multi-threading.
However, as soon as I run the threads, my main thread is blocked, thus preventing me from drawing the shapes and using the global variables. How can I get around this? What I ultimately want to achieve is, modify the global variables from two seperate functions running in their own thread and simultaneously draw the circles using the said global varibales
global_variable_1
global_variable_2
void function_1()
{
while(true)
{
//modifies global_variable_1
}
}
void function_2()
{
while(true)
{
//modifies global_variable_2
}
}
void MyOnPaint(HDC hdc)
{
Graphics graphics(hdc);
Pen pen(Color::Blue);
/* Uses global_variable_1 & global_variable_2 to
draw circles */
}
int APIENTRY _tWinMain(......)
{
/* Some initial code */
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GAZEPOINTEVALUATION));
/*Start threads*/
using namespace boost;
thread thread_1(function_1);
thread thread_2(function_2);
//Start threads
thread_1.join()
thread_2.join()
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
/* Some code */
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
/*CALL MY DRAWING METHOD*/
MyOnPaint(hdc);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
/* Some code */
default:
/* Some code */
}
return 0;
}

join calls will never return because your threads loop for ever. From the docs:
In order to wait for a thread of execution to finish, the join(),
__join_for or __join_until ( timed_join() deprecated) member functions of the boost::thread object must be used. join() will block the
calling thread until the thread represented by the boost::thread
object has completed.
You never enter your message loop, therefore.
If you remove the join calls, this should do something more like what you expect - in a more complex application you'd need to properly design thread scheduling and exit handling. Even as it stands, you will likely have to add some delay into the spawned threads to avoid pegging the CPU and possibly seeing other weirdness you are not expecting.

Related

delegate in UI Thread update from worker (XAML)

i want to update some GUI Elements within the GUI Thread from a WorkerThread.
The GUI (Class MainPage) specifies a delegate function like the following way.
HRESULT MainPage::delegateUpdateGUI(IXRDependencyObject* pSender, XREventArgs* pArgs) {
Mutex.lock();
...
Mutex.lock();
Sleep(20);
this-> m_textbox->SetText(counter_string);
}
A Delegate ptr is declared outside
IXRDelegate<XREventArgs, IXRDependencyObject> *m_delegateFunction;
and is loaded within the MainPage::OnLoaded Method:
m_delegateFunction = CreateDelegate(this, &MainPage::delegateUpdateGUI);
In my WorkerThread:
...
DWORD WINAPI WorkerProc(LPVOID pParam) {
Mutext.Lock();
Counter++;
...
Mutex.unlock(),
m_delegateFunction->Invoke(myMainPage, NULL);
Sleep(20);
}
When i run it with this Sleep(X) condition greater than 10ms it is working, but without that sleep calls an Exeception is thrown ....
Does anybody know why the exception is thrown and what is wrong or missing?

Terminating a Worker thread from a Parent thread - MFC

I've just started with learning MFC and I'm writing one dialog based application for better understanding of Multi-Threading.
The main dialog has a progress bar, a Start button and a Cancel button.
On click of the start button, i'm creating a worker thread to do some processing(through API call) and the main thread takes care of Progress bar.
I've defined a couple of Windows Messages to update and stop Progress bar status
WM_UPDATE_CONTROL
WM_STOP_CONTROL
Below is the code that i've created so far
HWND* phObjectHandle;
CWinThread* thread;
void CprogCtrlDlg::OnBnClickedStart() {
phObjectHandle = new HWND; // Set object handle for Worker thread
*phObjectHandle = GetSafeHwnd();
// create worker thread
if(NULL == (thread = AfxBeginThread(ThreadFunc, phObjectHandle))) {
EndDialog(IDCANCEL);
}
AfxMessageBox(L"Thread started");
// Set Progress bar to marquee
}
void CprogCtrlDlg::OnBnClickedCancel() {
// kill the Worker thread
}
UINT CprogCtrlDlg::ThreadFunc(LPVOID pParam) {
HWND *pObjectHandle = static_cast<HWND *>(pParam);
CprogCtrlImpDlg* threadDlg = (CprogCtrlImpDlg*) pParam;
return threadDlg->ThreadFuncRun(pObjectHandle);
}
UINT CprogCtrlDlg::ThreadFuncRun(HWND* pObjectHandle) {
::PostMessage(*pObjectHandle, WM_UPDATE_CONTROL, 0, 0);
// repetitive API CALL in a loop
::PostMessage(*pObjectHandle, WM_STOP_CONTROL, 0, 0);
AfxMessageBox(L"Thread completed");
return 0;
}
I want to terminate the Worker thread from a Parent thread, if a Cancel button is clicked.
I tried using TerminateThread()(though it wasn't a suggested one) but I couldn't kill the thread.
Please comment and share your thoughts on terminating a worker thread from a parent thread.
I'm using visual studio 2010 on Windows 7
TIA
I would amend your code something like this.
Have some member variables in your dialog class to hold the thread handle and an event handle (initialise to NULL in the constructor):
CWinThread* m_hThread;
HANDLE m_hKillEvent;
Use a static function as your thread entry point, pass the dialog this as the parameter, then delegate the call back to the class instance so you have access to all of the dialog's variables:
UINT ThreadFunc(LPVOID pParam)
{
// static thread func - delegate to instance
CprogCtrlDlg* pDlg = static_cast<CprogCtrlDlg*>(pParam);
return pDlg->ThreadFuncRun();
}
When you start the thread, create an event too:
void CprogCtrlDlg::OnBnClickedStart()
{
// create worker thread
m_hKillEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThread = AfxBeginThread(ThreadFunc, this);
AfxMessageBox(L"Thread started");
}
To kill the thread, just set the event and wait on the thread handle, which will get signaled on death:
void CprogCtrlDlg::OnBnClickedCancel()
{
// kill the Worker thread
SetEvent(m_hKillEvent);
// wait for it to die
DWORD dwRet = WaitForSingleObject(m_hThread->m_hThread, 5000);
if (dwRet == WAIT_TIMEOUT)
{
// thread failed to die after 5 seconds
// error handling (maybe TerminateThread here)
}
}
In the thread function (now in the dialog class) you can post messages to yourself to indicate progress and use a wait on the event to catch a kill request:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
while (true)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
// ... so this is part of your working loop ...
PostMessage(WM_UPDATE_CONTROL, 0, 1 /*2,3,4,...*/);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}
I've left out initialisation, cleanup of pointers, handles etc. but you get the general idea I hope.
There are several ways you can code the thread loop, you can do it like above where you periodically check to see if the event is signaled, or you can wait on the event to get signaled to do the work. Both are common patterns and often used together with two events - one for triggering work and the other for killing. See this answer for some important points to note if waiting on multiple events.
For a simple progress bar update, you can put the event check inside the work loop, something like this:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
for (int i = 0; i < 100; ++i)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
PostMessage(WM_UPDATE_CONTROL, 0, (LPARAM)i);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}

GTK+ Thread safety

I'm trying to use threads to manage several things in GTK+, however, as soon as I try to use any GUI function in the new thread, it locks up the GUI and this makes sense since GTK+ is not thread safe. Is there anyway around this?
Here's my code:
int main(int argc, char *argv[])
{
GError *error = NULL;
/* init threads */
g_thread_init(NULL);
gdk_threads_init();
/* init gtk */
gtk_init(&argc, &argv);
....
//Multithreaded functions
g_thread_create(argument_thread, (gpointer)label7, FALSE, &error );
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return 0;
}
void *argument_thread(void *args)
{
while(1)
{
gdk_threads_enter();
gtk_entry_set_text(entry2,"random stuff");
gdk_threads_leave();
}
}
Not sure if this could be an issue (don't know GTK) but maybe there is a race condition if the thread acquires the lock before the gtk_main has started.
Then you could try:
gdk_threads_enter();
//Multithreaded functions
g_thread_create(argument_thread, (gpointer)label7, FALSE, &error );
gtk_main();
gdk_threads_leave();
Moreover you should temporize your loop:
void *argument_thread(void *args)
{
while(1)
{
gdk_threads_enter();
gtk_entry_set_text(entry2,"random stuff");
gdk_threads_leave();
sleep(10);
}
}
I have resolved the problem using g_timeout e gthread:http://www.freemedialab.org/wiki/doku.php?id=programmazione:gtk:gtk_e_i_thread
Basically I use 3 functions, one that launches the thread, one that does the job without manipulating widgets (thread) and a third type that serves as a timeout timer checking every n seconds certain values ​​written by the thread and updates the ' graphic interface.
Or you can use "g_idle_add" : http://www.freemedialab.org/wiki/doku.php?id=programmazione:gtk:gtk_e_i_thread#versione_con_g_idle_add
gdk_threads_enter() and gdk_threads_leave() are deprecated from 3.6 version of Gtk.

MFC - Posting data via PostMessage to the GUI

I Read a few threads on how passing data from Workerthread to Main window(Dialog), but I still don't understand and still need help.
My workerthread should process some calculations and display the result during each loop to an edit on the GUI. I know, I should use PostMessage but since the calculation I'm doing implies a control element, I don't know how to solve this problem ...
//CWorkerThreadMgr.h manages the second thread
HRESULT Start (HWND hWnd);// from where the workerthread will be started
HWND m_hWnd ; //Window handle to the UI ;
HANDLE m_hTread; //handle of the worker thread
static UINT WINAPI ThreadProc( LPVOID lptest );
static UINT WINAPI ThreadProc( LPVOID lptest )
{
CWorkerThreadMgr* pCalculateMgr = reinterpret_cast< CWorkerThreadMgr*(lptest);
//The following operation:rand() *m_Slider.GetPos() should
//should be calculated and the result displayed each time in the edit box in the gui
for( UINT uCount = 0; uCount < 40; uCount++ ){
pCalculateMgr->rand() *m_Slider.GetPos();//?don't allowed to touch the gui!!
PostMessage(pCalculateMgr-> m_hWnd, WM_SENDCALCULATED_VALUE,wparam(rand() *m_Slider.GetPos(),0);
}
}
LRESULT CStartCalculationDlg::OnSendCalculatedValue( WPARAM Result, LPARAM )
{
// The resut should be displayed in the edit box
m_Calculation.Format(_T("%d"),???);
SetDlgItemText(IDC_CALCULATION, m_Calculation);
return 1;
}
void CStartCalculationDlg::OnHScroll(UINT nSBCode, UINT nPos,CScrollBar* pScrollBar)
{
m_SliderValue.Format(_T("%d"),m_Slider.GetPos());
SetDlgItemText(IDC_SLIDER_VALUE,m_SliderValue);
}
// Implementation in the CStartCalculationDlg.h
CWorkerThreadMgr m_WorkerThreadMgr //instance of the WorkerThreadMgr
CSliderCtrl m_Slider //member variable of the slider control
CString m_SliderValue // member variable of the edit box, where the current value of the
//slider will be displayed
CString m_Calculation // member variable of the edit box where the calculated
//result from the workerthread will be displayed via PostMessage
afx_msg LRESULT OnSendCalculatedValue( WPARAM, LPARAM );
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
The next probem is that, when my slider control is moved and gets a new value, the thread procedure should know it and update the value of the slider. How can I manage to do it?
Instead of reading the slider position from the worker thread, read it in the UI thread and make it available to the worker thread.
I'm really no expert in this field, but I've done some worker threads as explained here.
What I would do in your case is create a static variable, like the "running" flag used in the article linked above, to hold the current position of the slider. Then, in the OnHScroll handler set it to the appropriate value.
As long as you only write to that variable from one thread, you should not have synchronization issues.
From worker thread:
m_data = foo();
PostMessage(hWndMain, UWM_SOME_CUSTOM_MESSAGE, 0, 0);
From UI thread:
LRESULT CMainFrame::OnSomeCustomMessage(WPARAM wParam, LPARAM lParam)
{
CMyData data = m_pWorker->GetData();
// Do stuff...
return 0;
}
GetData must be guarded by a critical section:
CMyData CMyWorker::GetData()
{
// This critical section is used in the worker thread too, whenever m_data is accessed.
m_lock.Lock();
CMyData data = m_data;
m_lock.Unlock();
return data;
}
See CCriticalSection on MSDN.

Can't get my thread to execute with SetEvent and WaitForSingleObject

I'm trying to create a thread and let it run until my main signals it to start, which I think is done with SetEvent. But the code in the thread is never executed. Below is the bare code I have stripped down of (I think) unrelated functions. Is the algorithm correct ?
Here is what I thought it did :
When in the main, the thread is created, which means it'll run in the background. When the event is set (SetEvent), the thread picks it up at WaitForSingleObject and then execute the code in the thread, right ?
HANDLE hThread;
HANDLE Event;
DWORD Thread()
{
while(1)
{
wait = WaitForSingleObject(Event, INFINITE)
//This is where I want to execute something
}
}
int _tmain()
{
DWORD dw;
int i;
Event = CreateEvent(NULL,false,false,NULL);
hThread = CreateThread(NULL,0,Thread,EventA,0,NULL);
while(1)
{
if (condition is correct)
{
SetEvent(Event);
}
CloseHandle(Thread);
CloseHandle(Event);
}
return 0;
}
Thanks for having read.
Move CloseHandle lines out of the while loop.

Resources