MFC Multithreaded OLE controls
BRIAN_DEHAMER@HP-MountainView-om2.om.hp.com
Tuesday, October 01, 1996
Item Subject: cc:Mail Text
Environment: VC++ 4.2, NT 3.51
I'm in the process of using MFC to create an OLE control. The control
starts a thread that does some DB access work and then, when the
thread finishes, I want it to fire an event back up to the container.
According to Adam Denning's "OLE Controls Inside Out," I need to be
firing the event from the main control thread and not the worker
thread. With that knowledge, I decided that I would have the worker
thread post a message back to the main thread and have the event fired
in the course of handling the message. This is where I'm having the
problem. I'm either posting the message inproperly or I'm not
handling it correctly upon receipt. Here's a stripped down version of
my code. Any help available would be greatly appreciated.
//////////////////////////// test.h //////////////////////////////
class CTestCtrl : public COleControl
{
// Message maps
afx_msg void OnTest();
DECLARE_MESSAGE_MAP()
// Dispatch maps
afx_msg BOOL ExecuteThread();
DECLARE_DISPATCH_MAP()
// Event maps
void FireQueryComplete()
{FireEvent(eventidQueryComplete,EVENT_PARAM(VTS_NONE));}
DECLARE_EVENT_MAP()
static UINT QueryThread(LPVOID lpr);
// Dispatch and event IDs
public:
enum {
dispidExecute = 4L,
eventidQueryComplete = 1L,
};
};
//////////////////////////// test.c //////////////////////////////
//////////////////////////////////////////////////////////////////////
///////
// Message map
BEGIN_MESSAGE_MAP(CTestCtrl, COleControl)
ON_COMMAND(IDS_TEST, OnTest)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////
///////
// Dispatch map
BEGIN_DISPATCH_MAP(CTestCtrl, COleControl)
DISP_FUNCTION(CTestCtrl, "Execute", Execute, VT_BOOL, VTS_NONE)
END_DISPATCH_MAP()
//////////////////////////////////////////////////////////////////////
///////
// Event map
BEGIN_EVENT_MAP(CTestCtrl, COleControl)
EVENT_CUSTOM("QueryComplete", FireQueryComplete, VTS_NONE)
END_EVENT_MAP()
BOOL CTestCtrl::Execute()
{
HANDLE hThread;
idThread = GetCurrentThreadId();
hThread = AfxBeginThread(QueryThread, this);
return TRUE;
}
UINT CTestCtrl::QueryThread(LPVOID lpr)
{
CTestCtrl *ctrl = (CTestCtrl*)lpr;
/* Do thread stuff here */
PostThreadMessage(ctrl->idThread, IDS_TEST, 0, 0);
return 0;
}
void CTestCtrl::OnTest()
{
FireQueryComplete();
}
Thanks.
Brian De Hamer
Noel Burton-Krahn -- noel@harleystreet.com
Thursday, October 03, 1996
[Mini-digest: 2 responses]
First: Your PostThreadMessage and ON_COMMAND are wrong. see
PSS ID Number: Q142415
in the knowledge base. Make a WM_USER message and trap it in your app's
PreTranslateMessage.
Second: I have noticed problems with thread messages myself. see "Lost
thread messages" posted to this list. I haven't been able to confirm this,
but I believe that thread messages are often thrown away by
DispatchMessage(). Here's the scenario:
1) you post a thread message
2) the destination thread puts up a dialog, or some other gizmo that has
its own message loop (like CRectTracker)
3) The gizmo calls GetMessage() and gets your thread message
4) The gizmo doesn't know what to do with your message, so it calls
DispatchMessage() with your thread message
5) The problem now is that a thread message is not associated with a
window, so where could DispatchMessge send it? I suspect that it gets sent
to the void, never to be seen again.
Mind you, I still have to get confirmation on this. What I know, though is
that I lost Thread messages, but as soon as I sent messages to another
_window_ they always arrived.
So, I suggest you try:
1) posting messages to one of you main thread's windows
2) using MsgWaitForMultipleEvents()
--Noel
----------
From:
BRIAN_DEHAMER@HP-MountainView-om2.om.hp.com[SMTP:BRIAN_DEHAMER@HP-Mount
ainView-om2.om.hp.com]
Sent: Tuesday, October 01, 1996 1:55 PM
To: mfc-l@netcom.com
Subject: MFC Multithreaded OLE controls
Item Subject: cc:Mail Text
Environment: VC++ 4.2, NT 3.51
I'm in the process of using MFC to create an OLE control. The control
starts a thread that does some DB access work and then, when the
thread finishes, I want it to fire an event back up to the container.
According to Adam Denning's "OLE Controls Inside Out," I need to be
firing the event from the main control thread and not the worker
thread. With that knowledge, I decided that I would have the worker
thread post a message back to the main thread and have the event fired
in the course of handling the message. This is where I'm having the
problem. I'm either posting the message inproperly or I'm not
handling it correctly upon receipt. Here's a stripped down version of
my code. Any help available would be greatly appreciated.
//////////////////////////// test.h //////////////////////////////
class CTestCtrl : public COleControl
{
// Message maps
afx_msg void OnTest();
DECLARE_MESSAGE_MAP()
// Dispatch maps
afx_msg BOOL ExecuteThread();
DECLARE_DISPATCH_MAP()
// Event maps
void FireQueryComplete()
{FireEvent(eventidQueryComplete,EVENT_PARAM(VTS_NONE));}
DECLARE_EVENT_MAP()
static UINT QueryThread(LPVOID lpr);
// Dispatch and event IDs
public:
enum {
dispidExecute = 4L,
eventidQueryComplete = 1L,
};
};
//////////////////////////// test.c //////////////////////////////
//////////////////////////////////////////////////////////////////////
///////
// Message map
BEGIN_MESSAGE_MAP(CTestCtrl, COleControl)
ON_COMMAND(IDS_TEST, OnTest)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////
///////
// Dispatch map
BEGIN_DISPATCH_MAP(CTestCtrl, COleControl)
DISP_FUNCTION(CTestCtrl, "Execute", Execute, VT_BOOL, VTS_NONE)
END_DISPATCH_MAP()
//////////////////////////////////////////////////////////////////////
///////
// Event map
BEGIN_EVENT_MAP(CTestCtrl, COleControl)
EVENT_CUSTOM("QueryComplete", FireQueryComplete, VTS_NONE)
END_EVENT_MAP()
BOOL CTestCtrl::Execute()
{
HANDLE hThread;
idThread = GetCurrentThreadId();
hThread = AfxBeginThread(QueryThread, this);
return TRUE;
}
UINT CTestCtrl::QueryThread(LPVOID lpr)
{
CTestCtrl *ctrl = (CTestCtrl*)lpr;
/* Do thread stuff here */
PostThreadMessage(ctrl->idThread, IDS_TEST, 0, 0);
return 0;
}
void CTestCtrl::OnTest()
{
FireQueryComplete();
}
Thanks.
Brian De Hamer
-----From: "Luke Stephens"
I believe you need to do the following:
PostThreadMessage(ctrl->idThread, WM_COMMAND,IDS_TEST, 0);
or use ON_MESSAGE(IDS_TEST,OnTest)
| Вернуться в корень Архива
|