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

Q: How to get the (LPTHREAD_START_ROUTINE) address of a C++ function?

0 views
Skip to first unread message

Mark J. Hogan

unread,
Jan 8, 2000, 3:00:00 AM1/8/00
to
I know how to program Threads using the API calls. I can also write custom
controls. But, I can not figure out how to make call to CreateThread and
pass it a C++ function.

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


Mark J. Hogan

unread,
Jan 8, 2000, 3:00:00 AM1/8/00
to
I have found some examples and now have the Threads working. Here is a
declaration:

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

Raymond Chen

unread,
Jan 9, 2000, 3:00:00 AM1/9/00
to
>public:
> static UINT WaitForARing(LPVOID pObj);
>...
>UINT CListenERCtrl::WaitForARing(LPVOID pObj)
>{
>...
>}
>
>m_hThread = AfxBeginThread(WaitForARing, this);
>
>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...

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

Raymond Chen

unread,
Jan 10, 2000, 3:00:00 AM1/10/00
to
On Sun, 9 Jan 2000 22:00:29 -0600, "Mark J. Hogan"
<hog...@smtechnologies.com> wrote:
>Thanks for the suggestion, I tried it but it still doesn't work. I still
>get the Access Violation.

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.

Mark J. Hogan

unread,
Jan 10, 2000, 3:00:00 AM1/10/00
to
Raymond,

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

Raymond Chen

unread,
Jan 10, 2000, 3:00:00 AM1/10/00
to
On Mon, 10 Jan 2000 12:58:58 -0600, "Mark J. Hogan"
<hog...@smtechnologies.com> wrote:
>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.

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();

Mark J. Hogan

unread,
Jan 10, 2000, 3:00:00 AM1/10/00
to
>
> Now you get to debug the FireReceive() function
>

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

unread,
Jan 10, 2000, 3:00:00 AM1/10/00
to
If I understand it correctly, you're trying to raise an event from a
worker thread of an ActiveX Control. See this link:
http://www.mvps.org/vcfaq/com/1.htm

--
===============================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@geocities.com
===============================

Mark J. Hogan wrote in message ...

Mark J. Hogan

unread,
Jan 11, 2000, 3:00:00 AM1/11/00
to
> If I understand it correctly, you're trying to raise an event from a
> worker thread of an ActiveX Control. See this link:
> http://www.mvps.org/vcfaq/com/1.htm
>

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

unread,
Jan 11, 2000, 3:00:00 AM1/11/00
to
SendMessage makes it synchronous. Why didn't you use PostMessage
as I implied (BTW, the article is mine)? There's no need for any critical
sections here except for guarding the object state.

--
===============================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@geocities.com
===============================

Mark J. Hogan wrote in message ...

Mark J. Hogan

unread,
Jan 12, 2000, 3:00:00 AM1/12/00
to
I did not use PostMessage because the worker thread updates the properties
of the control (via a self pointer) and then fires the event (via the
PostMessage). The event has no parameters, so the programmer must get the
data from the properties of the control for each event. This is why I made
the control synchronous. This is also why I have the critical sections.

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

Alexander Nickolov

unread,
Jan 12, 2000, 3:00:00 AM1/12/00
to
BSTR should be sufficient:
HRESULT MyEvent([in] BSTR bstrData);

Mark J. Hogan

unread,
Jan 14, 2000, 3:00:00 AM1/14/00
to
Alexander,

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

unread,
Jan 14, 2000, 3:00:00 AM1/14/00
to
Thank you. I already forwarded your message along with instructions to
the webmaster in charge.

--
===============================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@geocities.com
===============================

Mark J. Hogan wrote in message ...

0 new messages