Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am trying to figure out how to access variables in my workerthread while it is doing work. What I have so far:

Workerthread has updated the data.
Postmessage to the UI.

UI calls GetData from worker thread.
C++
//Message Routine from Post Message in UI
LRESULT CContactFault::OnDeviceShortAddress(WPARAM, LPARAM)
{

	UINT data = m_ContactAnalysis.GetData();
	CsLoader = _T("%d");
	CsTmp.Format(CsLoader, data);
	MapFP.WriteString(CsTmp + "\n");

	return 1;
}

//Routine in workerthead class
UINT GetData()
{
   UINT data = m_data;
   return data;
}

My results are inconsistant and I have a feeling this has to do with sychchronizing the data in GetData. I have searched everywhere and cannot find a good example to do this with Lock Unlock.. If that is even the best way. Maybe someone can help me understand a good way to do this.
Posted
Updated 17-Apr-12 2:55am
v2

How about sending the data as part of the message you post to the UI? Especially as it's only one word of information:

C++
LRESULT CContactFault::OnDeviceShortAddress(WPARAM, LPARAM lparam)
{
    UINT data = reinterpret_cast<uint>(lparam);
    CsLoader = _T("%d");
    CsTmp.Format(CsLoader, data);
    MapFP.WriteString(CsTmp + "\n");
 
    return 1;
}


You'll have to remember to bung your worker's m_data in as the LPARAM in the call to Postmessage but it'll stop any synchronisation headaches.

Incidentally this trick also works if you have more data to post - allocate a structure, post the address of this to the UI. The UI can read the data and then delete the structure. Intercommunicating processes and asynchronous message transfer is one of the safest ways to do multi-threading around.

Cheers,

Ash

Edit as this effing editor loves "closing" tags I open when using C++ templates
 
Share this answer
 
v2
Comments
dsandru1 17-Apr-12 9:16am    
Thank you for your quick responce. For instance with the same example above, if I had multiple data:

LRESULT CContactFault::OnDeviceShortAddress(WPARAM, LPARAM lparam)
{
DataStruct *ds = new reinterpret_cast<datastruct>(lparam);
CsLoader = _T("%d, %d");
CsTmp.Format(CsLoader, ds->data1, ds->data2);
MapFP.WriteString(CsTmp + "\n");

delete ds;
return 1;
}

When passing the structure I would pass the pointer in the LPARAM section?
Thank you for giving me examples, it really helps since it has been a while since I have done any programming.
Aescleal 17-Apr-12 9:23am    
You don't need to do create a new DataStruct in the message handler. You do it in the thread just before you call post message:

//In thread...
DataStruct *ds( new DataStruct(d1, d2) );
PostMessage( ui_window, WM_MY_MESSAGE, 0, ds );

Then the message handler becomes:

LRESULT CContactFault::OnDeviceShortAddress(WPARAM, LPARAM lparam)
{
DataStruct *ds = reinterpret_cast(lparam);
CsLoader = _T("%d, %d");
CsTmp.Format(CsLoader, ds->data1, ds->data2);
MapFP.WriteString(CsTmp + "\n");

delete ds;
return 1;
}

(I've assumed the structure has a constructor and has a couple of members)

Cheers,

Ash
Espen Harlinn 17-Apr-12 10:39am    
Nice and simple - a 5 :-D
In your case you are only passing an UINT value. So just pass it using the WPARAM or LPARAM parameter.

When implementing a GetData() function, you should use locking inside that function and at all places where the data is written by the thread. An example:

C++
class CMyThreadClass
{
    CCriticalSection g_cs; // access globals shared by threads
};

UINT CMyThreadClass::GetData()
{
    CSingleLock singleLock(&g_cs);
    singleLock.Lock();
    UINT data = m_data;
    singleLock.Unlock(); // also done by destructor
    return data;
}
 
Share this answer
 
Comments
Aescleal 17-Apr-12 9:15am    
Beat you to be first to post on pushing the data through PostMessage.

+5 as you showed him how to lock for future reference.
Jochen Arndt 17-Apr-12 9:19am    
Thank you. +5 for you for the hint to pass an allocated structure.
Espen Harlinn 17-Apr-12 10:39am    
Nice and simple - a 5 :-D
I'm confused by your original problem. You say your results are "inconsistent" but are unclear as to either what that means or how you've decided they are "inconsistent".

As for locking, since you are dealing with a single value, UINT, and not a structure with multiple variables, there's no real need to lock / unlock the reference to it. As long as you have a single reader (get function) and a single writer (workerthread) there should not be any synchroization issues.

In fact, if this were not true for single values (int, bool, etc) then none of those algorithms that do "lock free access" would work, they all rely on the fact that a single atomic item can be accessed without a lock and still be consistent.

So, while the other answers provide some good advise, sending the data in a message, etc. I still do not know why your original method didn't work out for you. What is "Inconsistent"?
 
Share this answer
 
Comments
dsandru1 17-Apr-12 13:24pm    
I found the inconsistency to be in the hardware I was collecting data from. I still appreciate both solutions because they explained how to handle passing my information between threads. After seeing how this was done some other examples I previously found on the web began to make sense.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900