Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
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.
//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 17-Apr-12 3:51am
Edited 17-Apr-12 3:55am
JF201553.3K
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

How about sending the data as part of the message you post to the UI? Especially as it's only one word of information:
 
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
  Permalink  
v2
Comments
dsandru1 at 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(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 at 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 at 17-Apr-12 10:39am
   
Nice and simple - a 5 :-D
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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:
 
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;
}
  Permalink  
Comments
Aescleal at 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 at 17-Apr-12 9:19am
   
Thank you. +5 for you for the hint to pass an allocated structure.
Espen Harlinn at 17-Apr-12 10:39am
   
Nice and simple - a 5 :-D
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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"?
  Permalink  
Comments
dsandru1 at 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)

  Print Answers RSS
0 OriginalGriff 475
1 Maciej Los 349
2 Richard MacCutchan 220
3 BillWoodruff 219
4 Mathew Soji 160
0 OriginalGriff 8,759
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,639
3 Maciej Los 5,269
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web04 | 2.8.1411028.1 | Last Updated 17 Apr 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100