Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

afxbeginthread & LPVOID usage with multiple arguments -URGENT

725 views
Skip to first unread message

KK

unread,
Jan 17, 2005, 11:48:51 AM1/17/05
to
Greetings,
I'm newbie to MFC and with experts help here, I could manage to
begin a thread using afxbeginthread. This was possible when the thread
function ("run" in this case- see below) had zero input parameters. I
dont know how to exploit LPVOID to pass more parameters.
Could any please help me how to use the code(below) to work with a
thread function with some parameter say 'run(int arg)'
Thank you in advance,
-KK
P.S:
void CWasDlg::run()
{
//someStatementsHere
threadFlag=FALSE;
}
UINT CWasDlg::run(LPVOID p)
{
CWasDlg *me= (CWasDlg *)p;
me->run();
return 0;
}
void CWasDlg::OnOK()
{
threadFlag= TRUE;
AfxBeginThread(run,this);
}
void CWasDlg::OnCancel()
{
threadFlag= FALSE;
CDialog::OnCancel();
}

Bob Moore

unread,
Jan 17, 2005, 5:01:55 PM1/17/05
to
On 17 Jan 2005 08:48:51 -0800, "KK" <kewl...@yahoo.com> wrote:

>I
>dont know how to exploit LPVOID to pass more parameters.

All threads share the same process address space, so create a (global
scope) structure, put the address of the structure in the LPVOID
parameter, and cast the LPVOID back to a structure pointer in the
thread's run function so you can extract the data.

e.g.

// This is typed by hand, so there may be typos...

typedef struct tagThreadTable
{
HWND hMainWnd;
UINT uThreadOverMsg;

} ThreadTable;

ThreadTable mg_WorkThreadTable;

void CMainFrame::StartWorkerThread ()
{
mg_WorkThreadTable.hMainWnd = GetSafeHwnd();
mg_WorkThreadTable.uThreadOverMsg = m_uMyRegisteredMsg1;

m_pWorkerThread = AfxBeginThread (WorkerThreadRunFn, (LPVOID)&mg_WorkThreadTable);
}

UINT WorkerThreadRunFn (LPVOID pParam)
{
ThreadTable* pData = (ThreadTable*) pParam;

HWND hOwner = pData->hMainWnd;
UINT uPostWhenDoneMsg = pData->uThreadOverMsg;
.....


Of course you have to make sure your main thread and your worker never
try to access the structure at the same time (or protect them with a
critical section). It's never been a problem for me, and I use threads
quite a bit.

s.k.easley

unread,
Jan 18, 2005, 12:24:50 PM1/18/05
to
It looks like you're using two overloaded member functions called
run(). That's fine, but you can't use a member function as a worker
thread function. The calling conventions are different, mainly because
member functions have the implicit 'this' parameter.

As far a passing data into the worker thread, it looks like you're
using the LPVOID to pass a pointer to your CWasDlg object. I do that a
lot and it works great. It also gives you a convienient place to put
the CCriticalSection to protect against concurrent access.

Make run(LPVOID) a static function rather than a member function, and
make it a friend of your CWasDlg class so it can access CWasDlg data.
Then add a CCriticalSection object to CWasDlg and use it whenever you
access CWasDlg data.

Hope that helps.

Ed Weir (ComCast)

unread,
Feb 6, 2006, 1:50:31 PM2/6/06
to
"Bob Moore" <bo...@mvps.org> wrote in message
news:stcou0pgs7dgousb8...@4ax.com...

WHOA - this is a very BAD idea. A global structure to pass multiple
variables to a thread?! And then a critical section to protect your global
variables?? Rather defeats the whole purpose of multithrteading, does it
not?

Like a millipede walking on two legs!

Instead, create a new (OK, globally typedef'd or defined if you must)
structure for each new thread and marshal the variables for your thread.
NEVER pass variables to a thread that other instances have access to which
could cause unwanted conflicts. When the thread is done with the pointer it
can just delete it. There are a large number of ways to do this; an example
being something like:
typedef struct tagParams
{
int i;
CMyDlgClass* pDlg;
CString strTextData;

tagParam(int iVar, CMyDlgClass* pMyDlg, LPCTSTR pszTextData)
{ i = iVar; pDlg = pMyDlg; strTextData = pszTextData; }
} PARAMS, *PPARAMS;

then all you have to do is:
AfxBeginThread(MyWorkerThread, (PVOID) new tagParams(42, this, "This is My
Text Data"));

UINT MyWorkwerThread(PVOID p)
{
PPARAMS pParams = (PPARAMS) p;
UINT nRetCode = ERROR_SUCCESS;
if(pParams->i == 42)
nRetCode = pParams->pDlg->DoSomethingWith(pParams->strTextData);

... // yada
... // yada
... // yada
delete pParams;
return nRetCode;
}

This way you can spin as many threads as you have resources for and not
worry about data mungeing conflicts. It is a common mistake to allow
mutithreaded access to data and then spend hours trying to debug the
problems that arise because of it. Multithreading is a very powerful tool
when used properly. A major nightmare if not.

The example I just gave doesn't begin to address the synchronization issues
you will have to deal with, nor termination issues. After some practice and
losing a few tail feathers treatment of these issues will become second
nature to you, so rock on!

Cheers...!

0 new messages