您的位置:首页 > 其它

worker线程操作界面引起的死锁

2010-05-26 01:18 453 查看
一般来说涉及界面操作的工作都有UI线程完成,但是在多线程程序中worker子线程进行简单的界面操作也是常见的事情!worker线程和主线程(UI线程)同时更新界面时容易造成消息循环阻塞,引起死锁!引起消息循环阻塞的原因是worker线程没有自己的消息循环,其和主线程公用同一线程!引起死锁的原因是当子线程更新界面时需要发送消息向主线程消息队列,如果主线程没有wait或者sleep等该消息可以正常处理,但是如果主线程自身刚好也在更新相同的界面,这时子线程会等待主线程处理完更新界面消息才能得到响应!而主线程也会发现有线程正在更新这个界面,需要等待该线程处理完才继续自己的处理!哦,相互等待出现!

在多线程中,为了保持较好的交互性,一般遵循:

1、在主线程中最好不要用waitforsingleobject、waitformultipleobjects等阻塞消息循环的函数,否则界面会出现无响应现象!

2、一般情况下worker线程只处理后台工作,不要涉及界面操作(界面操作涉及太多的消息),否则主、子线程容易相互锁死!

3、对于子线程操作界面较多的情况,可以创建UI线程,建立自己消息循环!

工作中遇到了这种情况:worker子线程和主线程会更新相同的界面,子线程更新的同时主线程更新开始!为了正确更新和防止死锁,主线程必须在等待子线程更新完后进行自己的更新,同时保持继续响应后继消息!常用方法是采取Relay措施,延迟处理主线程更新,继续其他消息的处理!

Relay处理函数如下:
]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(TRUE)
{
MSG msg;
//响应其它消息的处理
while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
if(GetTickCount() - dwStart > dwTime)
return;
::Sleep(1);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐