小弟在写一个小程序,要用到多线程。在线程的主函数中调用::SetTimer()函数设置了一个定时器,也写了定时器回调函数,但是在调试过程中发现,必须得在线程主函数中添加 MSG msg;
while (1) 
    {
        GetMessage(&msg, NULL, 0, 0);
        DispatchMessage(&msg);        
    } 
定时器函数才会被调用,不明白为什么要这样?
另外我写的程序主框架是基于Dialog的,不知道和这些有没有关系?
新线程及定时器处理函数如下:CSnakeProMet sNake;
UINT TimerID;VOID CALLBACK SnakeMoveNext( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime)
{
sNake.SnakeMoveNext();
}DWORD WINAPI SnakeCtrProc(LPVOID pParam )
{
HWND hPicFrame =  ::GetDlgItem(AfxGetMainWnd()->m_hWnd, IDC_PICFRAME);
CWnd* moveFrame = CWnd::FromHandle(hPicFrame);  
sNake.SnakeCreate(moveFrame, 1);
sNake.DrawSnake(); TimerID = ::SetTimer(NULL, 0, 100, (TIMERPROC)SnakeMoveNext);
MSG msg;
while (1) 
    {
        GetMessage(&msg, NULL, 0, 0);
        DispatchMessage(&msg);        
    }   

return 0;
}
操作系统不是为没个应用程序维护一个消息队列吗? 而不是为线程维护消息队列。
请大侠回答!!

解决方案 »

  1.   

    SetTimer的第一个参数是什么?
    就是某一窗口句柄,楼主给了NULL参数,就是没有与任何窗口建立联系
    因此也就不能使用任何窗口的消息处理Timer与窗口一起使用才是MS的设计初衷
      

  2.   

    一般的windows应用程序都会有一个消息循环,而在mfc的应用程序中,我们使用的是消息映射,但还是能实现消息的正确分发。
    我的题目中,在设置定时器的最后一个参数为一个回调函数,此函数我理解应该在定时器溢出的时候由操作系统自动调用,也就是说这个定时器消息已经与其处理函数进行了关联。既然已经进行了关联为什么还要自己获取消息和分发消息呢?就算是需要,主程序中已经是实现了消息的分发,为什么还要分发一次呢?
      

  3.   

    首先需明确的一点是:每个Windows线程,创建开始时不拥有消息队列的,
    The system creates a thread's message queue when the thread makes its first call to one of the Win32 User or GDI functions. 然后需明确的是:消息循环是和某个线程相关的,消息循环中读取的都是和该线程相关的消息队列的消息。最后需明确的是:SetTimer创建了定时器,实际上是促使操作系统隔固定时间投递一个WM_TIMER消息出来,这个消息投递到哪里,
    当然是调用SetTimer时所在的线程的消息队列中了。
    这点请看MSDN的解释:
    An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.它这里的核心意思是:如果你调用SetTimer时指定lpTimerFunc参数,这个回调函数是在默认窗口过程处理WM_TIMER时调用的。最后,总结就是:
    如果调用SetTimer的线程没有构造消息循环,那么WM_TIMER消息就没有被处理,回调函数就没有地方被调用。
    同时,如果调用SetTimer以后,线程函数返回,线程结束,操作系统会撤销与该线程相关的所有数据结构,于是操作系统也不会再投递WM_TIMER消息了,也就是定时器也随着线程结束而消亡了。
      

  4.   

    多谢 fuzigege 接分!!