Archived

This topic is now archived and is closed to further replies.

Problems creating a thread with CreateThread()

This topic is 5265 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi All Im trying to create a thread that would check for input from the keyboard and mouse. I have a class called cl_input and my check for input method defined like so:
DWORD cl_input::CheckForInput(void)
So in my constructor I have:
// Clear

hThread = NULL;
DWORD threadID;

// Create the thread for input

hThread = CreateThread(NULL, 0, this->CheckForInput, NULL, 0, threadID);
However when I compile it I get the following error: input.h(50) : error C2664: ''CreateThread'' : cannot convert parameter 3 from ''unsigned long (void)'' to ''unsigned long (__stdcall *)(void *)'' I dont know how to typecast this if it even needs to be. Please Help. Thanks

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
typedef unsigned long (__stdcall TYPE_T*)(void *);

(TYPE_T)(this->CheckForInput)

Share this post


Link to post
Share on other sites
The third argument to CreateThread is a pointer to the thread function, it can have any name but must have the syntax

DWORD WINAPI ThreadProc(PVOID pParam);

The thread function is simply a function that contains the code to be exectued in the new thread.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
you can''t use a class'' (non-static) member function as a parameter to createthread.

the solution is to create a free helper function (or static member function). in the ctor use the helper with createthread, passing the this-ptr as the void*-parameter of the free function.

in your helper function, simply use the passed this-ptr to call any member function of your class.

Share this post


Link to post
Share on other sites

struct cl_input
{
Thread<cl_input> thrCheckInput;
unsigned int CheckForInput();
};

if(!thrCheckInput.Create(this, &cl_input::CheckForInput))
throw Error;



template <typename ParentClass>
struct Thread
{
public:
typedef void (*fpLogFunc)(const TCHAR*const);
fpLogFunc logfunc;

static void noLog(const TCHAR*const){}
Thread() : logfunc(&Thread::noLog), m_hThread(INVALID_HANDLE_VALUE), m_dwID(0), m_pParentClass(0)
{
}

~Thread()
{
if(IsValid())
{
if(!IsTerminated())
{
//ASSERTMSG(0, "Thread object being destroyed prior to thread termination!\n");

this->logfunc(SC("Thread object being destroyed prior to thread termination!\r\n"));
Join();
}
CloseHandle(m_hThread);
m_hThread=INVALID_HANDLE_VALUE;
}
}

HANDLE handle(){return m_hThread;}

typedef unsigned int (ParentClass::*MethodProc)(void);
typedef Event<false, false> tyEvent;
tyEvent m_evExit;

bool Create(ParentClass* pThis, MethodProc pThreadMethod, const char* const name = 0)
{
//ASSERTMSG(INVALID_HANDLE_VALUE==m_hThread, "Don''t call Thread<>::Create without calling Close!");

if(INVALID_HANDLE_VALUE!=m_hThread)
{
this->logfunc(SC("Closing previously created thread due to second Thread<>::Create\r\n"));
this->Close();//return false;

}

m_evExit.Reset();
m_pParentClass = pThis;
m_pMethodProc = pThreadMethod;
//m_hThread = (HANDLE)_beginthreadex(NULL, 0, &DefaultProc, this, 0, (UINT*)&m_dwID);

m_hThread = CreateThread(NULL, NULL, &DefaultProc, this, 0, &m_dwID);

if( (0==m_hThread) || (INVALID_HANDLE_VALUE==m_hThread) )
return false;
else
return true;
}
int ThreadID() {return m_dwID;}
bool IsExiting()
{
return this->m_evExit.IsSignaled();
}
bool Exit()
{
return m_evExit.Signal();
}
bool Join(DWORD dwTime_ms=5000)
{
CLock<> AutoLock(m_csLock);

if(this->IsValid())
{
//m_evExit.Signal();

if(this->WaitForTermination(dwTime_ms))
return true;
else
{
TCHAR szMsg[128];
tcscpy(szMsg, SC("* "));
tcscpy(&szMsg[tcslen(szMsg)], SC("Thread<> "));
tcscpy(&szMsg[tcslen(szMsg)], SC(" forcefully terminated\n"));
assert(tcslen(szMsg)<sizeof(szMsg));
this->logfunc(szMsg);
//Debug::Console.Out(szMsg);

return this->Terminate();
}
}
else
return true;
}

bool Close()
{
assert(INVALID_HANDLE_VALUE!=m_hThread);
//ASSERTMSG(IsTerminated(), "Terminate the thread prior to closing it''s handle!");

if(!IsTerminated())
{
this->logfunc(SC("Terminating thread on Thread<>::Close\r\n"));
Join(5000);
}
if(CloseHandle(m_hThread))
{
m_hThread=INVALID_HANDLE_VALUE;
return true;
}
else
return false;
}

bool IsValid() {return(INVALID_HANDLE_VALUE!=m_hThread);}
bool IsTerminated() {return (WAIT_OBJECT_0==WaitForSingleObject(m_hThread, 0));}
bool IsRunning() {return (WAITSCIMEOUT==WaitForSingleObject(m_hThread, 0));}

BOOL Suspend()
{
assert(INVALID_HANDLE_VALUE!=m_hThread);
return SuspendThread(m_hThread);
}

BOOL Resume()
{
assert(INVALID_HANDLE_VALUE!=m_hThread);
return ResumeThread(m_hThread);
}

/*
//reference, Win32 only
enum ePriority
{
TimeCritical = THREAD_PRIORITY_TIME_CRITICAL,
Highest = THREAD_PRIORITY_HIGHEST,
AboveNormal = THREAD_PRIORITY_ABOVE_NORMAL,
Normal = THREAD_PRIORITY_NORMAL,
BelowNormal = THREAD_PRIORITY_BELOW_NORMAL,
Lowest = THREAD_PRIORITY_LOWEST,
Idle = THREAD_PRIORITY_IDLE
};
*/

int LowestPriority() {return THREAD_PRIORITY_IDLE;}
int DefaultPriority() {return THREAD_PRIORITY_NORMAL;}
int HighestPriority() {return THREAD_PRIORITY_TIME_CRITICAL;}
int IncPriority(int priority)
{
switch(priority)
{
case THREAD_PRIORITY_TIME_CRITICAL:
return THREAD_PRIORITY_TIME_CRITICAL;

case THREAD_PRIORITY_HIGHEST:
return THREAD_PRIORITY_TIME_CRITICAL;

case THREAD_PRIORITY_ABOVE_NORMAL:
return THREAD_PRIORITY_HIGHEST;

case THREAD_PRIORITY_NORMAL:
return THREAD_PRIORITY_ABOVE_NORMAL;

case THREAD_PRIORITY_BELOW_NORMAL:
return THREAD_PRIORITY_NORMAL;

case THREAD_PRIORITY_LOWEST:
return THREAD_PRIORITY_BELOW_NORMAL;

case THREAD_PRIORITY_IDLE:
return THREAD_PRIORITY_LOWEST;

default:
assert(0);
return THREAD_PRIORITY_NORMAL;
}
}
int DecPriority(int priority)
{
switch(priority)
{
case THREAD_PRIORITY_TIME_CRITICAL:
return THREAD_PRIORITY_HIGHEST;

case THREAD_PRIORITY_HIGHEST:
return THREAD_PRIORITY_ABOVE_NORMAL;

case THREAD_PRIORITY_ABOVE_NORMAL:
return THREAD_PRIORITY_NORMAL;

case THREAD_PRIORITY_NORMAL:
return THREAD_PRIORITY_BELOW_NORMAL;

case THREAD_PRIORITY_BELOW_NORMAL:
return THREAD_PRIORITY_LOWEST;

case THREAD_PRIORITY_LOWEST:
return THREAD_PRIORITY_IDLE;

case THREAD_PRIORITY_IDLE:
return THREAD_PRIORITY_IDLE;

default:
assert(0);
return THREAD_PRIORITY_NORMAL;
}
}
int SetPriority(int priority)
{
if(0==SetThreadPriority(m_hThread, priority))
MKH_THROWONFAILURE(GetLastError());
return priority;
}
int GetPriority()
{
if(0==GetThreadPriority(m_hThread, priority))
MKH_THROWONFAILURE(GetLastError());
return priority;
}

bool WaitForTermination(DWORD dwTime_ms=INFINITE)
{
assert(INVALID_HANDLE_VALUE!=m_hThread);
return(WAIT_OBJECT_0==WaitForSingleObject(m_hThread, dwTime_ms));
}

protected:
static unsigned long __stdcall DefaultProc(void* pv)
{
if(pv==0) _asm{int 3}
assert(pv);
Sleep(10);
return reinterpret_cast<Thread*>(pv)->Run();
}
unsigned int Run()
{
try
{
assert(m_pParentClass);
assert(this);
assert(m_pMethodProc);
if(m_pParentClass && m_pMethodProc)
{
unsigned int x = (m_pParentClass->*m_pMethodProc)();
return x;
}
}
catch(...)
{
assert(0);//"Thread threw an uncaught exception"

throw;
}

return -3;
}
MethodProc m_pMethodProc;
ParentClass* m_pParentClass;

bool Terminate()
{
CLock<CCriticalSection> AutoLock(m_csLock);

if(INVALID_HANDLE_VALUE!=m_hThread)
if(TerminateThread(m_hThread, -42))
return true;
else
return false;
else
return true;
}

protected:
volatile HANDLE m_hThread;
DWORD m_dwID;
CCriticalSection m_csLock;
};

template <typename ParentClass>
struct CThread : Thread<ParentClass>
{
};


I have a version for pthreads now too...

Share this post


Link to post
Share on other sites