代码大致结构如下: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里面的代码却能正常继续运行。这是为什么呢?这个时候的消息循环倒底是什么样的?

解决方案 »

  1.   

    timer是系统自动到时后回调过来了的,关键是这里:
    if(0!=DoWork())
                m_listctrl.InsertItem(......);
    这个DoWork理本身就是消息循环处理,但是你这doword怎么停止呢?
    在主线程中不要使用WaitForSingleObject和WaitForMultipleObjects两个函数等待线程退出,其原因就是有导致程序死锁的隐患,特别是线程函数里调用了SendMessage或是直接操作了MFC对象,更易出现此种现象。
    你看下这里吧
    http://www.cppblog.com/fwxjj/archive/2009/04/01/78519.html
      

  2.   

    在主线程中我用的是MsgWaitForMultipleObjects,因为DoWork是运行在主线程中的。
    而在工作线程中的内容其实是串口收发,因为这个操作比较费时,如果放在主线程中,将导致界面无响应,所以移到了工作线程内。如果我将dlg.DoModal()改为
    CyDialog *pDialog = new CyDialog(this,false);//false表示非模态
    pDialog->ShowWindow(SW_SHOW)就没有任何问题,LISTCTRL操作正常。
      

  3.   

    在主线程中我用的是MsgWaitForMultipleObjects,因为DoWork是运行在主线程中的。
    而在工作线程中的内容其实是串口收发,因为这个操作比较费时,如果放在主线程中,将导致界面无响应,所以移到了工作线程内。如果我将dlg.DoModal()改为
    CyDialog *pDialog = new CyDialog(this,false);//false表示非模态
    pDialog->ShowWindow(SW_SHOW)就没有任何问题,LISTCTRL操作正常。
      

  4.   

    A也是响应CxDialog的一个按钮点击的函数。
      

  5.   

    A也是响应CxDialog的一个按钮点击的函数。
      

  6.   

    那响应OnButtonStopClicked()之后
    A没有办法响应了吧
      

  7.   


    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)就没有任何问题。何故?
      

  8.   

    还是得用F11啊。
    跟了一遍问题就出来了,原来是DispatchMessage给Block了。
      

  9.   

    DispathMessage被Block之后,DoWork也就被Block了,于是A也被Block了。