zoukankan      html  css  js  c++  java
  • 在主线程中慎用WaitForSingleObject (WaitForMultipleObjects)

    下面的代码我调试了将近一个星期,你能够看出什么地方出了问题吗?

    线程函数:
        DWORD WINAPI ThreadProc()
        {
            while(!bTerminate)
            {
                // 从一个链表中读取信息并且插入到CListCtrl中
                // CListCtrl的句柄是通过线程参数传递进来的
                for(;;)
                {
                   ReadInfoFromList();
                   InsertToCListCtrl();
                }
            }
        }


    主线程中使用CreateThread 启动线程。

    当想终止子线程时,在主线程中:
        bTerminate = TRUE;
        WaitForSingleObject(threadHandle, INFINITE);
    可是,以运行到WaitForSingleObject,子线程就Crash了。

    问题原因:
    后来我终于在InsertItem的反汇编中发现了如下的代码
    call dword ptr [__imp__SendMessageA@16 (7C141B54h)]
    可见,InsertItem是必须借助消息循环来完成任务的。如果我们在主线程中WaitForSingleObject了,必然导致主线程阻塞,也就导致了消息循环的阻塞,最终导致工作线程Crash掉了*_*

    解决方案:
    为了解决在主线程中Wait的问题,微软专门设计了一个函数MsgWaitForMultipleObjects,这个函数即可以等待信号(thread,event,mutex等等),也可以等待消息(MSG)。即不论有信号被激发或者有消息到来,此函数都可以返回。呵呵,那么我的解决办法也就出来了。
    将上面的WaitForSingleObject用下面的代码替换:
        while(TRUE)
        {
        
            DWORD result ;
            MSG msg ;
        
            result = MsgWaitForMultipleObjects(1, &readThreadHandle,
                FALSE, INFINITE, QS_ALLINPUT);
        
            if (result == (WAIT_OBJECT_0))
            {
                break;
            }
            else
            {
                PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
                DispatchMessage(&msg);
            }
        }



    总结:
    如果在工作线程中有可能涉及到了消息驱动的API,那么不能在主线程中使用 WaitForSingleObject一类函数,而必须使用上述的方案。

  • 相关阅读:
    bzoj3675 [Apio2014]序列分割
    bzoj3206 [Apio2013]道路费用
    bzoj3205 [Apio2013]机器人
    bzoj4241 历史研究
    bzoj2821 作诗(Poetize)
    bzoj2724 [Violet 6]蒲公英
    bzoj2811 [Apio2012]Guard
    bzoj2809 [Apio2012]dispatching
    PHP 文字,图片水印,缩略图,裁切成小图(大小变小)
    PHP文件下载方式
  • 原文地址:https://www.cnblogs.com/dongzhiquan/p/1994637.html
Copyright © 2011-2022 走看看