How to start a thread in Win32 C++

Started by
17 comments, last by Dominik_78 21 years, 4 months ago
Sorry for my dumness but i can''t figure out what i have to do at all - define my function static? is that all?

Advertisement
Define it static, then pass the "this" pointer to the thread function. Then you can cast the void pointer you get in the thread function to a pointer to your class and call whatever you want.

What I normally do is have a static function called StaticThreadProc, then delegate to the non-static ThreadProc.

Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions
Actually, beginthreadex is preferred over beginthread. Here is a macro that you might find helpful. You might also find these urls informative.


      /* createthreadex.h */#ifndef CREATETHREADEX_H_#define CREATETHREADEX_H_#pragma once#include <process.h>/* ---------------------------------------------------------------------------Q132078: "How to Use _beginthreadex() and _endthreadex()"http://support.microsoft.com/default.aspx?scid=KB;EN-US;q132078&    When developing a multithreaded Win32-based application with Visual C++,    you need to use the CRT thread functions to create any threads that call    CRT functions. To create and terminate threads, use either _beginthread()    and _endthread() or _beginthreadex() and _endthreadex().    If you use the Win32 APIs CreateThread() and ExitThread() instead,    some of the CRT functions used in the thread will not work.    You need to use the CRT functions to both create and end the threads    or you lose the memory that the CRT allocates for the thread.    In addition to preventing memory leaks, using _beginthreadex places    a structured exception handling frame around the thread function    so that the signal function and floating point exceptions work correctly.See also:Win32 Q&A, MSJ July 1999http://www.microsoft.com/msj/0799/win32/win320799.htmWin32 Q&A, MSJ October 1999http://www.microsoft.com/msj/1099/win32/win321099.htmHere are two macro overlays to facilatate this usage:Note:The thread that uses CreateThreadEx to launch new threads shouldalso dispose of any generated thread handle using CloseHandle.    HANDLE MyThread = CreateThreadEx(...);    ...    CloseHandle(MyThread);--------------------------------------------------------------------------- */typedef unsigned (__stdcall *StartAddressT)(void*);#define CreateThreadEx(                             lpThreadAttributes,                             dwStackSize,                                    lpStartAddress,                                 lpParameter,                                    dwCreationFlags,                                lpThreadId                                  )                                                ( (HANDLE) _beginthreadex(                     	    (void *)        (lpThreadAttributes),       	(unsigned int)  (dwStackSize),          	    (StartAddressT) (lpStartAddress),           	(void *)        (lpParameter),          	    (unsigned int)  (dwCreationFlags),          	(unsigned int *) (lpThreadId) ) )#define ExitThreadEx(dwExitCode) _endthreadex((unsigned int)dwExitCode)#endif /* CREATETHREADEX_H_ */      


Edit: for some reason the source tags are mangling the macro. Viewing the page source indicates the macro remains in place, albeit damaged. Given the overwhelming amount of code this macro is moot anyway. However, those urls are worth reviewing.


"Beautiful maiden," answered Candide, "when a man is in love, is jealous, and has been flogged by the Inquisition, he becomes lost to all reflection."


[edited by - lessbread on December 6, 2002 4:59:35 PM]
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Thought I''d add that the Boost Library (www.boost.org) has a pretty nice, clean, multithreading and synchronisation section.

Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions

  // The classclass ThreadedClass{public:  ThreadedClass();  static DWORD WINAPI threadInit( void * tc_arg );  void someMethod();}; DWORD WINAPI ThreadedClass::threadInit( void * tc_arg ){  ThreadedClass * tc = reinterpret_cast<ThreadedClass *>(tc_arg);  tc->someMethod();  // function dispatch} // in some function somewhere{  ...  ThreadedClass tc;  DWORD id;  HANDLE hThread = CreateThread( NULL, 0, ThreadedClass::threadInit, &tc, 0, &id );  ...}  
thanks for the code supply - it would be morning over there till i managed it on my own - it i ever would have.

thank you
I would do something like the -- untested -- code that follows:

  #include <iostream>#include <memory>#define NOMINMAX#include <windows.h>struct Foo{	DWORD ThreadProc1(void*)	{		std::cout << "Inside Foo::ThreadProc1" << std::endl;		return 0;	}	DWORD ThreadProc2(void*)	{		std::cout << "Inside Foo::ThreadProc2" << std::endl;		return 0;	}};struct Bar{	DWORD ThreadProc(void*)	{		std::cout << "Inside Bar::ThreadProc1" << std::endl;		return 0;	}};template <typename T>struct ThreadInfo{	typedef T class_type;	typedef DWORD(T::* function_type)(void*);		T* obj;	function_type function;	void* data;	ThreadInfo(class_type* f, function_type fp, void* d) : obj(f), function(fp), data(d) {}};template <typename T>DWORD WINAPI ThreadDispatch(void* data){	std::auto_ptr<ThreadInfo<T> > ti(static_cast<ThreadInfo<T>*>(data));	return ((ti->obj)->*(ti->function))(ti->data);}template <typename T>HANDLE CreateThread(SECURITY_ATTRIBUTES* sa, SIZE_T stackSize, T* object, DWORD(T::* threadRoutine)(void*), void* parameters, DWORD creationFlags, DWORD* tid){	std::auto_ptr<ThreadInfo<T> > ti(new ThreadInfo<T>(object, threadRoutine, parameters));	HANDLE rv = CreateThread(sa, stackSize, ThreadDispatch<T>, static_cast<void*>(ti.get()), creationFlags, tid);	if(NULL != rv)	{		ti.release();	}	return rv;}// In practice, you''ll normally not need all the parameters, so a convenience overload is provided.template <typename T>HANDLE CreateThread(T* object, DWORD(T::* threadRoutine)(void*), void* parameters){	return CreateThread(NULL, 0, object, threadRoutine, parameters, 0, NULL);}int main(){	using namespace std;	auto_ptr<Foo> foo(new Foo);	HANDLE thread = CreateThread(foo.get(), &Foo::ThreadProc1, NULL);	WaitForSingleObject(thread, INFINITE);	CloseHandle(thread);	auto_ptr<Bar> bar(new Bar);	thread = CreateThread(bar.get(), &Bar::ThreadProc, NULL);	WaitForSingleObject(thread, INFINITE);	CloseHandle(thread);}  
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/
If you''re a generic kinda guy, this helper-class lets you turn any class method into a thread.


  template <typename ParentClass>class Thread	{	public:		Thread() : 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");					Exit();					}				CloseHandle(m_hThread);				m_hThread=INVALID_HANDLE_VALUE;				}			}				HANDLE handle(){return m_hThread;}				typedef UINT (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)				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;			}				bool Exit(DWORD dwTime_ms=5000)			{			Lock<> AutoLock(m_csLock);						if(IsValid())				{				m_evExit.Signal();				if(WaitForTermination(dwTime_ms))					return true;				else					{					char szMsg[128];					strcpy(szMsg, "* ");					//strcpy(&szMsg[strlen(szMsg)], typeid(*this).name());					strcpy(&szMsg[strlen(szMsg)], "Thread<> ");					strcpy(&szMsg[strlen(szMsg)], " forcefully terminated\n");					Debug::Console.Out(szMsg);					return 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())				Exit(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 (WAIT_TIMEOUT==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);			}				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			};				BOOL SetPriority(ePriority priority)			{			assert(INVALID_HANDLE_VALUE!=m_hThread);			return SetThreadPriority(m_hThread, 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)			{			assert(pv);			Sleep(10);			return reinterpret_cast<Thread*>(pv)->Run();			}		UINT Run()			{			try				{				assert(m_pParentClass);				assert(this);				assert(m_pMethodProc);				if(m_pParentClass)					{					UINT x = (m_pParentClass->*m_pMethodProc)();					return x;					}				}			catch(...)				{				ASSERTMSG(0, "Thread threw an uncaught exception");				throw;				}						return -3;			}		MethodProc m_pMethodProc;		ParentClass* m_pParentClass;								bool Terminate()			{			Lock<CriticalSection> 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;		CriticalSection m_csLock;	};  



Example use:
struct SomeClass{Thread thread;UINT Run();void Initialize()   {   BOOL bResult = this->thread.Create(this, Run);   }void Shutdown()   {   this->thread.Exit();   }};UINT SomeClass::Run(){while(!this->thread.m_evExit.WaitFor(sleepTime_ms))   {   //Thread code goes here   }} 


A single class can have more than one type of thread this way.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
now it is running and everything is fine.

am I right if I think I just have to give an other class in that last pointer to run a function from that class...

I just want to write some code down to make it threaded (processing input) i already coded it i an class and if I could now make it run with just switching the pointer/function that is called it would be greate.

anyway thank you - you guy''s realy help me a lot!
I hope I can help people with what i have learned today too someday!

This topic is closed to new replies.

Advertisement