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.