>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.
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.
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...!