Passing class member function as a controlling function to AfxBeginThread (VC++)!

In Visual C++ usually we use AfxBeginThread function to create a Thread which will run the piece of code concurrently. AfxBeginThread function can be useful to create both worker thread and an user-interface thread. This article explains the first flavor of AfxBeginThread function which is useful to create worker threads in VC++.

The Syntax of AfxBeginThread function is:

CWinThread* AfxBeginThread( 
   AFX_THREADPROC pfnThreadProc, 
   LPVOID pParam, 
   int nPriority = THREAD_PRIORITY_NORMAL, 
   UINT nStackSize = 0, 
   DWORD dwCreateFlags = 0, 
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  
);

Here first and second arguments are important. If you do not provide any values to the rest of the arguments, this function will take the default values.

First argument is the pointer to the controlling function (or thread proc) which will execute in a Thread. The function prototype should be the following:

UINT __cdecl MyThreadProc(LPVOID pParam);

Usually this function will be declared in outside of the class. If you want to provide your class’s member function as a controlling function, you need to declare your class member function as a static member function. You can call other member functions of your class in controlling function through instance of your class.

class MyClass
{
public:
	static UINT MyThreadProc(LPVOID pParam);
};

Or, you can declare the controlling function as a friend of your class. So, the controlling function can access your class’s members also (static or non-static).

class MyClass
{
public:
	friend UINT MyThreadProc(LPVOID pParam);
};

The Second argument in AfxBeginThread function is the parameter to pass to the controlling function. You can use this parameter in your controlling function. Usually you can pass any value through this parameter; but it is always advisable to provide meaningful / useful data through this parameter. For ex: if your class’s member function is the controlling function, it is useful to pass your class’s pointer through this parameter. So, that you can call your class’s member function through this pointer.

Once AfxBeginThread is successfully executed, this function will return a pointer to CWinThread object. You can use this pointer to suspend or resume the worker thread.

Following is the complete example:

/* MyClass.h */
class MyClass
{
public:
	static UINT MyThreadProc(LPVOID pParam);

	void CreateWorkerThread();

private:
	void SomeFunction();
};
/* MyClass.cpp */
UINT MyClass::MyThreadProc(LPVOID pParam)
{
	MyClass *pMyClass = reinterpret_cast(pParam);

	if ( pMyClass != NULL )
	{
		/* You can access class's members */
		pMyClass->SomeFunction();
	}

	/* Your code here	*/

	return (0);
}

void MyClass::CreateWorkerThread()
{
	CWinThread *pWinThread = AfxBeginThread(MyThreadProc, this, 0U, CREATE_SUSPENDED);

	if ( pWinThread != NULL )
	{
		/* Thread started in SUSPENDED mode. Resume the thread. */
		pWinThread->ResumeThread();
	}
}

void MyClass::SomeFunction()
{
	/* Your code here */
	AfxMessageBox(_T("SomeFunction"));
}

by Code Steps

Leave a Reply