MFC工作线和UI主线程互锁问题的解决方法

3 篇文章 0 订阅
在以下代码中,线程Thread退出时,可能会要UI线程互锁
void CTagScanPCDlg::StopRead()
{
       if (m_hEvent != NULL) //线程结束等待事件
       {
              SetEvent(m_hEvent);
       }
       if (m_hThreadRead != NULL)
       {    
              WaitForSingleObject(m_hThreadRead,INFINITE);     //等待线程结束
              DWORD dwExitCode = 0;
             
              m_hThreadRead = NULL;
       }           
       m_hEvent = NULL;
}
DWORD WINAPI CTagScanPCDlg::ReadThread(LPVOID lpParam)
{
	//……
	while (WaitForSingleObject(pDlg->m_hEvent,0) == WAIT_TIMEOUT)
	{
		//……
		pDlg->SetDlgItemText(IDC_TAGGROUP,(LPCTSTR)szTextTitle);   //操作UI元素
		//……
	}
	//……
}


究其原因,是因为WaitForSingleObject函数会使线程的释放CPU时间,类似于Sleep的行为,如果此时 Work线程执行到操作UI元素的代码,但此时UI线程事实上已经处于休眠状态,因此操作UI元素的代码要等到UI线程被唤醒才会返回,这样一来,UI线程和Work线程便陷于互相等待的境地,死锁便由此发生。
解决方法:

既然死锁的原因是由于UI线程和Work线程的互相等待,那我们就尽量避免这种情况的发生。在StopRead函数中作如此修改:

if (m_hEvent != NULL)     //线程结束等待事件
{
	SetEvent(m_hEvent);
	Delay(10000,m_hDelayEvent)         
	//Delay为一延时函数,m_hDelayEvent为由CreateEvent创建的事件,创建于Work线程创建之前,当m_hDelayEvent被重置时,Delay函数便会返回
}

在ReadThread函数返回前,加如下代码:

SetEvent(pDlg->m_hDelayEvent);        //重置m_hDelayEvent

如此改动之后,由UI线程不会陷入长时间休眠,因此Work线程访问UI的代码也不会陷入等待状态,死锁便不会发生。

Delay函数如下:

void Delay(DWORD dwTime,HANDLE hEvent)
{
       DWORD dwStart = GetTickCount();
       if (hEvent != NULL)
       {
              while(WaitForSingleObject(hEvent,0) == WAIT_TIMEOUT)
              {
                     MSG msg;
                     //响应其它消息的处理
                     while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                     {
                            ::TranslateMessage(&msg);
                            ::DispatchMessage(&msg);
                     }
                     if(GetTickCount() - dwStart > dwTime)
                            return;
                     ::Sleep(1);
              }
       }
       else
              while(1)
              {
                     MSG msg;
                     //响应其它消息的处理
                     while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                     {
                            ::TranslateMessage(&msg);
                            ::DispatchMessage(&msg);
                     }
                     if(GetTickCount() - dwStart > dwTime)
                            return;
                     ::Sleep(1);
              }
 
}


原链接地址——

http://blog.sina.com.cn/s/blog_5ee42ba30100cbjm.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值