读书人

线程操作UI元素的有关问题

发布时间: 2013-03-28 10:20:24 作者: rapoo

线程操作UI元素的问题
在一个对话框 按钮事件中执行
OnBtnThread()
{
flag = false;
handle = CreateThread(0,0,Test_Thread,this,0,NULL);
}

DWORD WINAPI Test_Thread(PVOID pThis)
{
CActiveXTestDlg *pDlg = (CActiveXTestDlg *)pThis;
pDlg->Test();
return 0;
}

void Test()
{
for (int i = 0;i < 100000;i++)
{
m_list.InsertItem(i,"dsfsadfasdfdsfsdfsd");
m_list.SetItemText(i,1,"adfsdfsdfsd");
m_list.SetItemText(i,2,"adfsdfsdfsd");
m_list.SetItemText(i,3,"adfsdfsdfsd");
m_list.SetItemText(i,4,"adfsdfsdfsd");
if (flag == true)
{
break;
}
}
}
即,利用线程来执行一个更新操作,若标志位为TRUE,则退出。

OnDestroy()
{
flag = true;
if (handle != 0)
{
::WaitForSingleObject(handle,INFINITE);\\卡在当前行
handle = NULL;
}
}
关闭对话框后,此时程序卡住。但是调试断点时,发觉线程并未执行循环操作,且,未进入break;
就这么一直卡住,对此感到很诧异。除非,等待循环跑完,再退出就OK。
虽然知道UI是线程不安全的,要用windows消息进行操作,但就这个例子,还是不明白。
希望高手能够深入解释下。

另外,在实际编程过程中,可能UI是实时更新变化的,如果Post过多的消息,则可能导致界面卡死,即便使用UI线程,也未必完全能够解决。

期待高手!!
[解决办法]
原因很简单。
InsertItem是通过SendMessage的方式,其返回的前提是Messag Loop在运行中。
当插入过多的Item的并且还未插入结束,关闭Dialog,这时候跑到
::WaitForSingleObject(handle,INFINITE);\\卡在当前行
结果当前线程挂起,因而同时message loop也停止了。
结果InsertItem也返回不了,线程也结束不了,于是死锁!


[解决办法]
::WaitForSingleObject(handle,INFINITE);\\卡在当前行
----------------
不卡才怪!
你调用WaitForSingleObject时如果没有信号,UI的线程就会被挂起
这是工作线程调用m_list.InsertItem(i,"dsfsadfasdfdsfsdfsd");这些函数
内部是会用SendMessage发消息给UI线程的,但是这时UI线程已经挂起了
消息循环也不工作了,InserItem之类的函数就会被阻死
InsertItem被阻塞死 Test_Thread线程一直退不出,UI线程自然在WaitForSingleObject时也会等不到信号
死锁啦!典型的死锁问题

读书人网 >VC/MFC

热点推荐