Click to See Complete Forum and Search --> : Issues with Threading a Function [VC++6]


Shaitan00
February 10th, 2006, 02:27 PM
Simply put I am trying to THREAD a function that checks the registry of Remote Machines to determine the GROUP as follows:


// HEADER DEFINTIONS OF FUNCTIONS
VOID SetGroup (const LIST);
static INT SetGroupThreadProc (const LIST);

// Description: Spawn the thread to determine Group
SetGroup (const LIST lst)
{
static HANDLE hev = NULL;
... do the preparation work ...

DWORD dwLPID;
hev = (HANDLE)BEGINTHREADEX (
NULL, 0,
SetGroupThreadProc (lst),
this,
0,
&dwLPID
);
}

INT SetGroupThreadProc (const LIST p)
{
... For each station in LIST p check the registry remotely ...
... build the GROUP ...
... Save the GROUP to the local REGISTRY ...
_endthreadex( 0 );
return 0;
}


Thing is this "SEEMS" to work (I can debug through the thread/function, the LIST p is valid and the function determines the GROUP and writes it to the local registry correctly and everything...
Problem is my program now generates ACCESS VIOLATIONS, I just can't figure out why or where ... so as I test I un-threaded my function to see if it still occurs and it does NOT - so the issue must lie (somehow/somewhere) with the way my thread is working.

Looking at the code above, am I doing something wrong? Specifically, I was wondering about the following points:
- Do I need a "CloneHandle (hev);" somewhere?
- Can I pass in arguments (LIST p) the way I am doing it? Does this break the "BEGINTHREADEX" requirements somehow? am I doing this wrong?
- In MSDE the example of BEGINTHREADEX has the function passed in as "&SecondThreadFunc" (notice the &) but mine does NOT, could this be causing issues? If so how do I fix it?
- Do I need to somehow close/stop/remove the Thread after it is finished? I thought when "SetGroupThreadProc" the Thread would automatically delete/remove itself no?
Or ANYTHING else you can think of ...

Any help, hints, ideas, comments, would be greatly appreciated.
Thanks,

Siddhartha
February 10th, 2006, 02:33 PM
What is BEGINTHREADEX?

The API in question is beginthreadex, and you should look the MSDN documentation up to see that the thread-function's (SetGroupThreadProc) prototype doesn't match specifications.

Shaitan00
February 10th, 2006, 03:02 PM
Siddhartha: BEGINTHREADEX is beginthreadex (sorry).
So, what about the Prototypes don't match (I have read the MSDN documentation many times - I see there are some differences but I need to find a way for it to work for me also).

So, what rule/specification am I breaking exactly?
I need to pass the LIST into SetGroupThreadProc and this was the only way I found that it compiled correctly - could you provide more details?

Meaning, is it because I am passing in an argument? Not using Void*? Not passing in my function with & ???
Thanks,

kirants
February 10th, 2006, 03:44 PM
Thread proc expects a LPVOID.

I don't know what LIST is, but assuming it is an object, you are better off passing it's pointer..

Also, note , you don't do something like this when you pass it to beginthreadex ( third parameter )

SetGroupThreadProc (lst),

What that means is, the SetGroupThreadProc function is called and it's return value is used as the thread procedure, clearly not what you want.

You can do something like this:

struct ThreadParam
{
LISt lst;
}

// Description: Spawn the thread to determine Group
SetGroup (const LIST lst)
{

ThreadParam* pParam = new ThreadParam;
//make a copy of the list and pass it to thread
pParam->lst = lst;
DWORD dwLPID;
hev = (HANDLE)BEGINTHREADEX (
NULL, 0,
SetGroupThreadProc,
(void*)pParam,
0,
&dwLPID
);
}

INT SetGroupThreadProc (void* pParam)
{
//get the list object
ThreadParam* pThreadParam = (ThreadParam*)pParam;
... For each station in pThreadParam->lst p check the registry remotely ...
... build the GROUP ...
... Save the GROUP to the local REGISTRY ...
_endthreadex( 0 );
return 0;
}

Siddhartha
February 10th, 2006, 03:44 PM
So, what about the Prototypes don't match (I have read the MSDN documentation many times - I see there are some differences but I need to find a way for it to work for me also).Prototypes must match.

See this sample (http://www.codeguru.com/forum/showthread.php?t=312452) and match your's with the one here.
I need to pass the LIST into SetGroupThreadProc and this was the only way I found that it compiled correctly Compilation is no guarantee that the usage is correct.

Meaning, is it because I am passing in an argument? Because you are passing an argument incorrectly. Thats why.

The 4th parameter of _beginthreadex is meant for the argument to be passed to the thread, use it to pass the LIST, or a pointer to it as applicable. (At this moment, you are actually passing 3rd argument incorrectly, and passing this pointer as a LIST object in the 4th argument).

Alternatively, pass no argument, but keep your LIST object in a globally accessible state - say in a Singleton.

Here is a sample -
class CMySharedDataSingleton
{
public:
static CMySharedDataSingleton * GetInstance ()
{
if (!CMySharedDataSingleton ::m_pInstance)
CMySharedDataSingleton::m_pInstance = new CMySharedDataSingleton ();

return CMySharedDataSingleton::m_pInstance;
};

void SetList (const LIST & lstData)
{
m_lstData = lstData;
};

LIST& GetList ()
{
return m_lstData;
};

private:
CMySharedDataSingleton () {};
CMySharedDataSingleton & operator = (const CMySharedDataSingleton &);
CMySharedDataSingleton (const CMySharedDataSingleton &);

static CMySharedDataSingleton * m_pInstance;

LIST m_lstData;

};

CMySharedDataSingleton * CMySharedDataSingleton::m_pInstance = NULL; And accessing this is as simple as -
// Inside main thread - set the value of the object to be shared
CMySharedDataSingleton::GetInstance ()->SetList (lstYourListData);
And inside worker thread... // Inside worker thread
CMySharedDataSingleton::GetInstance ()->GetList ();
Just in case you want to know more about singletons... read this (http://www.codeguru.com/forum/showpost.php?p=1232679&postcount=5).