线程同步的问题

kenryHuang 2002-12-24 03:53:38
我开了一个线程去做某个循环,在循环中有个BOOL变量来判断是否退出。。
CWinThread* m_pWinThread = AfxBeginThread(SendThread, (LPVOID)NULL,
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL);
if (m_pWinThread != NULL)
{
m_pWinThread->m_bAutoDelete = FALSE;
m_pWinThread->ResumeThread();
m_bStopTransport = FALSE;
return TRUE;
}

线程函数是这样的:
UINT SendThread(LPVOID lpParam)
{
while (true) {
if (m_bExit) // m_bExit判断是否退出的BOOL变量
break;
// do something...
}
return 1;
}


比如线程在运行一半的时候,我想结束,这时设置m_bExit为true; 代码如下
void StopThread()
{
if (m_pWinThread != NULL) {
m_bExit = TRUE;
BOOL bRet = WaitForSingleObject(m_pWinThread->m_hThread, 5000);
if (bRet == WAIT_OBJECT_0)
AppendMessage(_T("Wait success!\n"));
else
AppendMessage(_T("Wait time out!\n"));

}
}


结果每次都是等待超时,让我奇怪的是,当m_bExit = TRUE;以后,程序就阻塞了
那个线程函数SendThread也没有执行,按书上的说法,当Wait一个线程的时候,
主线程(执行等待函数的那个)会挂起,时间都分配给等待的那个线程去执行,
当等待的那个线程返回以后,Wait函数也被激发,从而返回。。。

可是为什么我这里等待和被等待的都被冻结,而一直到超时以后,那个SendThread
才会继续执行呢?
...全文
39 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
zzyx 2002-12-26
  • 打赏
  • 举报
回复
我认为这个条件下m_bExit赋值不会产生死锁。
这样简单的线程同步情形使用变量足够了,用不着事件,临届区等。

你如果声明m_bExit为 volatile 来避免循环优化,应该不会出现你所说的问题。
finix 2002-12-25
  • 打赏
  • 举报
回复
BOOL bRet = WaitForSingleObject(m_pWinThread->m_hThread, INFINITE);
change to:
BOOL bRet = WaitForSingleObject(m_pWinThread->m_hThread, 5000);
finix 2002-12-25
  • 打赏
  • 举报
回复
because of use m_pWinThread->m_bAutoDelete = FALSE;
plz remember delete m_pWinThread
finix 2002-12-25
  • 打赏
  • 举报
回复
我简单测试了一下代码如下:
BOOL bExit=FALSE;//全局
CWinThread* m_pWinThread;//全局

UINT SendThread(LPVOID lpParam)
{
while (true)
{
if (bExit) // m_bExit判断是否退出的BOOL变量
break;
TRACE("work");
}
return 1;
}

void CChildFrame::OnStart()
{
m_pWinThread = AfxBeginThread(SendThread, (LPVOID)NULL,THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL);
if (m_pWinThread != NULL)
{
m_pWinThread->m_bAutoDelete = FALSE;
m_pWinThread->ResumeThread();
}
}
void StopThread()
{
if (m_pWinThread != NULL)
{
bExit = TRUE;
BOOL bRet = WaitForSingleObject(m_pWinThread->m_hThread, INFINITE);
if (bRet == WAIT_OBJECT_0)
TRACE(_T("Wait success!\n"));
else
TRACE(_T("Wait time out!\n"));
}
}

void CChildFrame::OnStop()
{
StopThread();

}
结果是work.................无数
按下stop后Wait success!
ml7575 2002-12-25
  • 打赏
  • 举报
回复
你在调用waitforsingleobject之前,在想结束的时候,有没有先设置关闭的事件setevent,我也是用waitforsingleobject都没问题。
kenryHuang 2002-12-25
  • 打赏
  • 举报
回复
有个问题我还没说明,线程函数里面其实没有循环,真正的循环是
在另外一个成员函数里面,跟这个是否有关系?
UINT SendThread(LPVOID lpParam)
{
//利用lpParam传递this参数
CMyClass* pThis = (CMyClass *)lpParam;
pThis->DoThread();
}

UINT CMyClass::DoThread()
{
while (true) {
if (m_bExit) // m_bExit判断是否退出的BOOL变量
break;
// do something...
TRACE("Thread is running!");
}
return 1;

}



kenryHuang 2002-12-25
  • 打赏
  • 举报
回复
各种方法都试过了。。总之没有用。
//我后来用了如下互斥代码
CCriticalSection cs;
cs.Lock();
m_bExit = TRUE;
cs.Unlock();

//然后用了一个循环判断线程是否退出。
while (TRUE) {
bRet = GetExitCodeThread(m_pWinThread->m_hThread, &dwCode);
if (bRet && dwCode == STILL_ACTIVE)
TRACE(_T("Thread is still active!\n"));
else
break;
}

结果是一直显示Thread is still active!
我在我的线程函数里面也加了一句:
UINT SendThread(LPVOID lpParam)
{
while (true) {
if (m_bExit) // m_bExit判断是否退出的BOOL变量
break;
// do something...
TRACE("Thread is running!");
}
return 1;
}

但是一旦调用设置m_bExit的函数,就一直显示Thread is still active!
从不显示Thread is running!,这显然表明自那以后线程函数就一直没有任何
运行的机会,一直都是在那个循环里面打转,而线程函数没有运行,也永远
不会退出,所以循环永远不会break;


而我觉得整个程序中只有StopThread设置了m_bExit,其他的都是读取
应该不会死锁吧。原因到底在哪里呢?


nustbobo 2002-12-25
  • 打赏
  • 举报
回复
试一下用临界区互锁
kenryHuang 2002-12-25
  • 打赏
  • 举报
回复
to mz02005(mz):
InterlockedExchangePointer这个函数在哪个头文件中申明的?
我怎么在MSDN中没有找到?我到是发现了一个InterlockedExchange函数
谢谢!
mz02005 2002-12-25
  • 打赏
  • 举报
回复
欧,不行。总之,两个县城访问m_bExit那需要互锁。
参考一下同步吧!
mz02005 2002-12-25
  • 打赏
  • 举报
回复
BOOL m = TRUE;
ASSERT(InterlockedExchangePointer((void*) m_bExit, (void*) &m));
mz02005 2002-12-25
  • 打赏
  • 举报
回复
m_bExit = TRUE;这句扶植语句改用下面的函数来实现试试看。

InterlockedExchangePointer
finix 2002-12-25
  • 打赏
  • 举报
回复
try: not to set autodelete flag
kenryHuang 2002-12-25
  • 打赏
  • 举报
回复
没有,我从来没有用SetEvent(...)等
就是一个单纯的WaitForSingleObject(...)
kenryHuang 2002-12-24
  • 打赏
  • 举报
回复
我的m_bExit是成员变量,为了简化,我这样写了。
所有的函数都是一个类里面!
UINT SendThread(LPVOID lpParam)是static成员!
m_pWinThread也是成员变量
season11 2002-12-24
  • 打赏
  • 举报
回复
我觉得可能是m_bExit设置的问题,你把他设置成全局变量看看怎么样!
关注!

15,466

社区成员

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

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