In the constructor of one of my classes I call the Windows function CreateThread as last operation. The thread is created to execute immediately and I pass the this pointer of my class as lpParameter.
In the thread procedure I cast the parameter passed back to a pointer of my class and name it pThis.
I can see that pThis points to the same memory location as the this pointer I passed when I called CreateThread. However if I look at the member variables accessed by pThis->... they all have wrong values.
I expected the value of this->member_variable used in the class to which the this pointer belongs to be the same as the one I get when writing pThis->member_variable in the thread's procedure.
If I call CreateThread in another member function (not the constructor) everything behaves correctly.
Hence the question: Is it forbidden to call the Windows function CreateThread from within the constructor of a C++ class? If yes, what is the problem?
Clarification:
1) I can confirm that the object always exists. The object gets out of scope only when the entire program ends. As I already said: calling CreateThread from some other member function does work.
2) Corrected the 'wired' typo, should have been 'weird', sorry.
Some code:
I try to post code snippets reducing things to the bare minimum while maintaining the 'faulty' parts.
class CTimerW32 : public CTimer
{
public:
CTimerW32();
~CTimerW32();
private:
static void CALLBACK TimerCallback(LPVOID lpParam, BOOLEAN bReason);
static DWORD WINAPI WaitCompletition(LPVOID lpParam);
private:
HANDLE m_hCompletitionEvent;
HANDLE m_hCompletitionThread;
bool m_bStartDeferred;
};
You can safely ignore the baseclass CTimer as it is just an abstract baseclass enabling build on different platforms.
CTimerW32::CTimerW32()
{
m_bStartDeferred= false;
m_hCompletitionEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
m_hCompletitionThread= CreateThread(NULL, 0, WaitCompletition, this, 0, NULL);
}
Here I can see that m_hCompletitionEvent is valid after the call to CreateEvent.
DWORD WINAPI CTimerW32::WaitCompletition(LPVOID lpParam)
{
CTimerW32* pThis;
DWORD dwRet;
pThis= (CTimerW32*)(lpParam);
while (true) {
// just wait for the completition event to be signaled
dwRet= WaitForSingleObject(pThis->m_hCompletitionEvent, INFINITE);
// ...
if (pThis->m_bStartDeferred) {
// ...
}
}
Here things are going wrong in the call to WaitForSingleObject. As already stated the this pointer of the object of class CTimerW32 (now pThis) still has the same value as the this pointer during thread creation. However the handle in pThis->m_hCompletitionEvent seems to be random data. It is not the value observed after the call to CreateEvent in the constructor.