Example:
void CListenERCtrl::WaitEvent(LPVOID lpvParam)
{
....
}
m_hThreadEvent = CreateThread(
NULL,
0L,
(LPTHREAD_START_ROUTINE)WaitEvent,
hPipe,
0,
&m_dwThreadIdEvent);
Can this be done? If not, how can I write a multi threaded CONTROL? How
does CWinThread work? I tried use it but I can not make the correlation
between CreateThread API and the CWinThread programming methods?
Thanks,
Mark J. Hogan
...
public:
static UINT WaitForARing(LPVOID pObj);
...
UINT CListenERCtrl::WaitForARing(LPVOID pObj)
{
...
}
m_hThread = AfxBeginThread(WaitForARing, this);
This runs fine. But, WaitForARing CANNOT call a NON-static function such as
a FireReceive event function.
What I am trying to do is to create a generic NamedPipe messaging control to
send a message string, ID and other info. The Listener control creates a
WaitForARing thread that basically calls CreateNamedPipe and
ConnectNamedPipe and waits for a call. When a call comes in, an new thread,
AnswerTheLine, is started to answer the line. AnswerTheLine processes the
call and then needs to call the FireReceive event function to signal the
control's event.
What is happening is ALL of the threads(i.e., static functions) CAN NOT see
the control's class data. Therefore I have to create a Global pointer to
the control and then have the threads access the data and fire the events
via the pointer (m_pThis->UpdateData or m_pThis->FireReceive()). The
m_pThis->FireReceive() function causes the control to crash with an access
violation. This is the error I am getting while running a test VB Exe in
the VC IDE.
---------------------------
Microsoft Visual C++
---------------------------
Unhandled exception in Test.exe (MSVBVM60.DLL): 0xC0000005: Access
Violation.
---------------------------
OK
---------------------------
Any help is appreciated.
Thanks,
Mark
"Mark J. Hogan" <hog...@smtechnologies.com> wrote in message
news:un#9uejW$GA....@cppssbbsa02.microsoft.com...
No, your WaitForARing method uses the pObj parameter to get the
class data.
UINT CListenERCtrl::WaitForARing(LPVOID pObj)
{
CListERCtrl *self = reinterpret_cast<CListenERCtrl*>(pObj);
// now use "self" as your "this" pointer.
}
--
(My return address is intentionally invalid to foil spammers. Delete the
".---" to get my real address. I do this on my own time with my own money;
my responses are not to be considered official technical support or advice.
Personal requests for assistance will be ignored.)
Hey waitasecond, that access violation you're getting isn't even
coming from your code. Perhaps you're passing invalid parameters
to some function (possibly a race condition in your code) or you
are doing multithreaded actions on an object that wasn't designed
to be multithreaded, or perhaps you are justplain corrupting
memory (using the object after destroying it).
Try debugging your application -- see what you're doing when the
AV occurs. Your sample program was way too big.
And why did you make so many of your functions static? The only
one that needs to be static is the one that you pass to
CreateThread.
Thanks for helping. Here is what I tried and why.
> Hey waitasecond, that access violation you're getting isn't even
> coming from your code. Perhaps you're passing invalid parameters
> to some function (possibly a race condition in your code) or you
> are doing multithreaded actions on an object that wasn't designed
> to be multithreaded, or perhaps you are justplain corrupting
> memory (using the object after destroying it).
Correct, the access violation is coming from FireReceive() function. The
FireReceive() was created by VC 6 (SP3)'s MFC ClassWizard. FireReceive()
was created by adding an ActiveX event called Receive with no parameters.
This brings up a question. Is the MFC capable of producing a multithreaded
control? i.e., can multiple threads all call the FireReceive() function
safely? Even if I use critical sections?
>
> Try debugging your application -- see what you're doing when the
> AV occurs. Your sample program was way too big.
>
When debugging the control, the control crashes when it calls the
FireReceive() function (via the self->FireReceivePublic() function) from
within one of the Threads. I posted the code so that you could look at the
pieces that you may have wanted to look at in the context of the control,
not for you to look at the whole thing and critique it.
> And why did you make so many of your functions static? The only
> one that needs to be static is the one that you pass to
> CreateThread.
Why the number of static funcs? Well, I am trying everything to figure this
out. The Threads can't access a NON static function, so I was making the
helper functions static. I just changed the code so that ONLY the threads
are static and the threads reference the helper functions via the self->
pointer. But, It still blows up at the same place.
Thanks,
Mark
You can't just create an object on one thread and start calling
it on another. You have to marshal the interface across threads.
This is especially important if the object is not
multithread-aware (marked "Free" or "Both" threading model).
>When debugging the control, the control crashes when it calls the
>FireReceive() function (via the self->FireReceivePublic() function) from
>within one of the Threads.
Now you get to debug the FireReceive() function
>The Threads can't access a NON static function, so I was making the
>helper functions static.
Yes it can. It's just that the threadstart function must be
static. All the other functions can be regular methods. For
example, here's a common trick:
DWORD ThreadFunction(); // a regular method
static DWORD StaticThreadFunction(LPVOID pObj) {
CObject self = reinterpret_cast<CObject*>(pObj);
// now invoke the function the C++ way
return self->ThreadFunction();
How can I debug an internal function? FireReceive() is declared as a call to
FireEvent. See below:
// Event maps
// AFX_EVENT(CListenERCtrl)
void FireReceive()
{FireEvent(eventidReceive,EVENT_PARAM(VTS_NONE));}
// AFX_EVENT
DECLARE_EVENT_MAP()
// Dispatch and event IDs
I have NOT found any location in VC6 where I can tell it to build and
compile as multithread control.
Mark
--
===============================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@geocities.com
===============================
Mark J. Hogan wrote in message ...
This was my exact problem. I opted for the simple solution of using
SendMessage to send a message to the WindowProc function. Before I make a
call to SendMessage, I update the control's properties via the self pointer.
This seems to be working.
I also created CriticalSection around the thread's SendMessage call and
around the call to FireReceive() in the WindowProc function.
Thanks,
Mark
--
===============================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@geocities.com
===============================
Mark J. Hogan wrote in message ...
I have NEVER figured out how to pass a string parameter through an event.
This is why I had to make the control synchronous. Also, there is a thread
that takes the initial calls and hands them off to a newly created worker
thread (the one with the PostMessage). This way the control is not blocked,
it is always ready to receive messages.
Do you know how do you pass strings thru to an event procedure? I tried the
LPCTSTR and the BSTR* types and they both cause errors. All I need is a
small example and I can fix this and some other controls that I have.
Thanks for the help, it is greatly appreciated.
Mark
"Alexander Nickolov" <agnic...@geocities.com> wrote in message
news:eHSBJ1JX$GA....@cppssbbsa02.microsoft.com...
By accident I found a MSDN example of a multuthreaded control and they used
the PostMessage solution too. They show how to handle a control with and
witout a window.
Here is the information:
FILE: Fireev.exe Fires Events from a Second Thread
ID: Q157437
You may want to add this reference to your web page.
Thank,
Mark
--
===============================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@geocities.com
===============================
Mark J. Hogan wrote in message ...