代码大致结构如下:void CxDailog::OnButtonStopClicked()
{
CyDialog dlg;
dlg.DoModal();
}void CxDailog::A()
{
ResetEvent(hEvent);
SetTimer(1,1000,NULL); while(true)
{
if(0!=DoWork())
m_listctrl.InsertItem(......);
else
break;
}
}int CxDailog::DoWork()
{
HANDLE hThread = CreateThread(......,threadProc......);
if(!hThread)return 0; while(MsgWaitForMultipleObjects(1,&hThread,FALSE,INFINITE,QS_ALLEVENTS) == WAIT_OBJECT_0+1)
{
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))DispatchMessage(&msg);
} CloseHandle(hThread);
return 1;
}int threadProc(...)
{
HANDLE hEvent = (HANDLE)((thread_prarm*)param)->eventExit;
While(true)
{
if(WaitForSingleObject(hEvent,0)==WAIT_OBJECT_0)break; //Do real work
} return 0;
}void CxDailog::OnTimer()
{
//Update dialog caption
static int i = 0;
TCHAR szText[12];
_stprintf(szText,TEXT("%d"),i++);
SetWindowText(szText);
}
现在的问题是在A的处理过程中,因为在DoWork函数里有消息循环,所以可以点击按钮stop(对应的处理函数为OnButtonStopClicked)。
在CyDialog对话框弹出来以后,发现m_listctrl.InsertItem(......)这一句无法往LISTCTRL中插入行了,但是OnTimer里面的代码却能正常继续运行。这是为什么呢?这个时候的消息循环倒底是什么样的?
{
CyDialog dlg;
dlg.DoModal();
}void CxDailog::A()
{
ResetEvent(hEvent);
SetTimer(1,1000,NULL); while(true)
{
if(0!=DoWork())
m_listctrl.InsertItem(......);
else
break;
}
}int CxDailog::DoWork()
{
HANDLE hThread = CreateThread(......,threadProc......);
if(!hThread)return 0; while(MsgWaitForMultipleObjects(1,&hThread,FALSE,INFINITE,QS_ALLEVENTS) == WAIT_OBJECT_0+1)
{
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))DispatchMessage(&msg);
} CloseHandle(hThread);
return 1;
}int threadProc(...)
{
HANDLE hEvent = (HANDLE)((thread_prarm*)param)->eventExit;
While(true)
{
if(WaitForSingleObject(hEvent,0)==WAIT_OBJECT_0)break; //Do real work
} return 0;
}void CxDailog::OnTimer()
{
//Update dialog caption
static int i = 0;
TCHAR szText[12];
_stprintf(szText,TEXT("%d"),i++);
SetWindowText(szText);
}
现在的问题是在A的处理过程中,因为在DoWork函数里有消息循环,所以可以点击按钮stop(对应的处理函数为OnButtonStopClicked)。
在CyDialog对话框弹出来以后,发现m_listctrl.InsertItem(......)这一句无法往LISTCTRL中插入行了,但是OnTimer里面的代码却能正常继续运行。这是为什么呢?这个时候的消息循环倒底是什么样的?
if(0!=DoWork())
m_listctrl.InsertItem(......);
这个DoWork理本身就是消息循环处理,但是你这doword怎么停止呢?
在主线程中不要使用WaitForSingleObject和WaitForMultipleObjects两个函数等待线程退出,其原因就是有导致程序死锁的隐患,特别是线程函数里调用了SendMessage或是直接操作了MFC对象,更易出现此种现象。
你看下这里吧
http://www.cppblog.com/fwxjj/archive/2009/04/01/78519.html
而在工作线程中的内容其实是串口收发,因为这个操作比较费时,如果放在主线程中,将导致界面无响应,所以移到了工作线程内。如果我将dlg.DoModal()改为
CyDialog *pDialog = new CyDialog(this,false);//false表示非模态
pDialog->ShowWindow(SW_SHOW)就没有任何问题,LISTCTRL操作正常。
而在工作线程中的内容其实是串口收发,因为这个操作比较费时,如果放在主线程中,将导致界面无响应,所以移到了工作线程内。如果我将dlg.DoModal()改为
CyDialog *pDialog = new CyDialog(this,false);//false表示非模态
pDialog->ShowWindow(SW_SHOW)就没有任何问题,LISTCTRL操作正常。
A没有办法响应了吧
void CxDailog::OnButtonControlClicked()
{
CyDialog dlg;
dlg.DoModal();
}void CxDialog::OnButtonStopClicked()
{
SetEvent(m_hEvent);
}void CxDailog::A()
{
ResetEvent(hEvent);
SetTimer(1,1000,NULL); while(true)
{
if(0!=DoWork(hEvent))
m_listctrl.InsertItem(......);
else
break;
}
}int CxDailog::DoWork(HANDLE hEventExit)
{
HANDLE hThread = CreateThread(......,threadProc,(PVOID)hEventExit);
if(!hThread)return 0; while(MsgWaitForMultipleObjects(1,&hThread,FALSE,INFINITE,QS_ALLEVENTS) == WAIT_OBJECT_0+1)
{
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))DispatchMessage(&msg);
} CloseHandle(hThread);
return 1;
}int threadProc(PVOID param)
{
HANDLE hEvent = (HANDLE)param;
While(true)
{
if(WaitForSingleObject(hEvent,0)==WAIT_OBJECT_0)break; //Do real work
//Send requeset to commport
//Receive response from commport
} return 0;
}void CxDailog::OnTimer()
{
//Update dialog caption
static int i = 0;
TCHAR szText[12];
_stprintf(szText,TEXT("%d"),i++);
SetWindowText(szText);
}
因为每一次receive from commport都是一个比较费时间的操作(大于100ms),所以只能将这部分放入工作线程中。
但是我又不能让它跟主线程同步工作,这样会导致很多别的问题,所以主线程需要等待工作线程结束,我用的是MsgWaitForMultipleObjects。现在的问题是当CyDialog对话框DoModal之后,往CxDialog的ListCtrl中InsertItem会被阻塞然后貌似被丢弃,但同时CxDialog的OnTimer函数响应正常。
如果把DoModal改成使用非模式对话框然后ShowWindow(SW_SHOW)就没有任何问题。何故?
跟了一遍问题就出来了,原来是DispatchMessage给Block了。