怎么确定从WinThread继承的类已经启动完毕,可以给他发消息了(160分求解,还有一个帖子在基础版了)

elabs 2003-11-06 09:22:51
另一个帖子在这了
http://expert.csdn.net/Expert/topic/2433/2433839.xml?temp=.2540552


我有一个CRequestManager 类定义如下
class CRequestManager : public CWinThread
{
DECLARE_DYNCREATE(CRequestManager)
CRequestManager();
protected:
virtual ~CRequestManager();

// Generated message map functions
//{{AFX_MSG(CRequestManager)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
private:
void onResponse(WPARAM wParam, LPARAM lParam);
};




在类里边有相应的自定义的消息响应宏和函数。

BEGIN_MESSAGE_MAP(CRequestManager, CWinThread)
//{{AFX_MSG_MAP(CRequestManager)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
ON_THREAD_MESSAGE( DEV_RESPONSE_COMPLETE, onResponse )
END_MESSAGE_MAP()

void CRequestManager::onResponse(WPARAM wParam, LPARAM lParam)
{
}




在主程序中要启动这个线程类,然后给他发消息,却发现有时候会消息发送失败
CRequestManager* m_pCRequestManager;

CRuntimeClass* pCRequestManager = RUNTIME_CLASS( CRequestManager ) ;

if( ::lstrcmp( pCRequestManager->m_lpszClassName , "CRequestManager" ) )
{
return WFS_ERR_INTERNAL_ERROR;
}
m_pCRequestManager =
(CRequestManager*)::AfxBeginThread(pCRequestManager ) ;

//这里发送消息有时候会失败,如果加上延时则没有问题,那现在我想知道到底什么时候才可以往这个线程中发消息。

m_pCRequestManager->PostThreadMessage(DEV_RESPONSE_COMPLETE, (UINT)1234, 0)
...全文
72 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhucde 2003-11-11
  • 打赏
  • 举报
回复
BOOL CMyThread::InitInstance()
的return TRUE;前
elabs 2003-11-11
  • 打赏
  • 举报
回复
最后顺便问问,在我的BOOL CRequestManager::InitInstance()
方法中用不用再返回

return CWinThread::InitInstance();

就是这么结尾?还是我现在直接返回TRUE即可。

elabs 2003-11-11
  • 打赏
  • 举报
回复
好,问题解决,三天后放分,看看还有没有更好的解决方法,顺便说说我的解决之道。

首先,zhucde(【风间苍月】) 和 jiangsheng(蒋晟.Net) 说得都没有错误,把他们说得组合起来就是正确答案,但是写出来代码里边还有sleep感觉有点别扭。我的解决方法就是,在
BOOL CRequestManager::InitInstance()
{
Sleep(5000);//这个只是模拟初始化动作所需要时间

PostThreadMessage(DEV_INIT_COMPLETE, (UINT)1234, 0);

return TRUE;
}
这里再去发送一个消息来取消信号量。

void CRequestManager::onInitComplete(WPARAM wParam, LPARAM lParam)
{
HANDLE m_Semaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"{0CE15660-56B3-4447-9AD3-794DABC93EAB}");
if( m_Semaphore != NULL)
{
ReleaseSemaphore(m_Semaphore,1,0);
CloseHandle(m_Semaphore);
}
else
{
CloseHandle(m_Semaphore);
}
}
因为既然自己可以发消息了,那外边也是可以发消息了。

主线程中
HANDLE m_Semaphore = NULL;

DWORD dwWaitResult = 0;

m_Semaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"{0CE15660-56B3-4447-9AD3-794DABC93EAB}");

if( m_Semaphore == NULL)
{
CloseHandle(m_Semaphore);
m_Semaphore = CreateSemaphore(NULL, 0, 1, "{0CE15660-56B3-4447-9AD3-794DABC93EAB}");
}

dwWaitResult = WaitForSingleObject(m_Semaphore,-1);

if (dwWaitResult == WAIT_TIMEOUT)
{
dwWaitResult = ReleaseSemaphore(m_Semaphore,1,0);
CloseHandle(m_Semaphore);
return WAIT_TIMEOUT;
}
CloseHandle(m_Semaphore);

BOOL rc = m_pCRequestManager->PostThreadMessage(DEV_RESPONSE_COMPLETE, (UINT)1234, 0);

这里再发消息就不会出现问题了。
蒋晟 2003-11-11
  • 打赏
  • 举报
回复
//这里发送消息有时候会失败,如果加上延时则没有问题
发送消息是不会失败的,除非没有进入消息循环。
确定InitInstance成功执行。
elabs 2003-11-11
  • 打赏
  • 举报
回复
zhucde(【风间苍月】) :

这个我好像也是试验过了,但是好像也是不对。那个CMyThread初始化方法返回后就可以给它发送消息吗??
elabs 2003-11-10
  • 打赏
  • 举报
回复
jiangsheng(蒋晟.Net):

我知道你的意思,但是你在线程中怎么知道初始化完毕的?

也就是说,你在那个类中什么地方写那个信号量。
蒋晟 2003-11-10
  • 打赏
  • 举报
回复
可以用事件通知线程的初始化已经完成,并且修改全局变量的值(注意修改时时用临界区)
elabs 2003-11-10
  • 打赏
  • 举报
回复
好像还是不行,没有任何效果,发送消息失败。
elabs 2003-11-07
  • 打赏
  • 举报
回复
好,回去试试,可以的话立刻结了帖子。
vcforever 2003-11-07
  • 打赏
  • 举报
回复
你在你的从CWinThread派生类的构造函数中将成员变量m_bAutoDelete设置为false
再试一试呢!
elabs 2003-11-07
  • 打赏
  • 举报
回复
dawndu(东南飞) :
这个我也想过,但是你在这个类中怎么知道它已经准备好了,也就是什么时候去发这个事件。
newslxw 2003-11-07
  • 打赏
  • 举报
回复
up
dawndu 2003-11-07
  • 打赏
  • 举报
回复
可以在线程起来后通知主线程它准备好了,可以用一个事件对象来实现
elabs 2003-11-07
  • 打赏
  • 举报
回复
vcforever(霓裳羽衣):
你的方法我试验过了,发送消息依然是失败,加上延时后问题解决,希望有更好的解决办法。
谢谢

继续等待答案
vcforever 2003-11-06
  • 打赏
  • 举报
回复
这种现象的确是存在的,原因我想应该你用AfxBeginThread()函数启动一个UI线程的时候,他会进入这个从CWinThread派生出来的UI线程的初始化函数中(InitInstance函数中)进行一些初始化的工作,这个初始化是需要时间的,如果在初始化不完全的情况下,使用了AfxBeginThread() 函数返回的指针就会出现问题,楼主的程序中出现问题的地方我想就是这个原因,解决这个问题除了给他加个延时(让线程完成初始化工作)外,你也可以在启动线程的时候以挂起的方式启动一个线程,让他先完成初始化,然后用ResumeThread执行线程就可以了,如你可以这样启动线程:
m_pCRequestManager =
(CRequestManager*)AfxBeginThread(
pCRequestManager,
THREAD_PRIORITY_NORMAL
0,
CREATE_SUSPENDED ) ;
ASSERT(m_pCRequestManager);
m_pCRequestManager->ResumeThread();
执行完线程之后你就可以向这个线程发送消息了

m_pCRequestManager->PostThreadMessage(DEV_RESPONSE_COMPLETE, (UINT)1234, 0);

希望对你有所帮助!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧