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

线程函数:

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一类函数,而必须使用上述的方案。

在主线程中慎用WaitForSingleObject (WaitForMultipleObjects)的更多相关文章

  1. Linux 下子线程 exit code 在主线程中的使用

    Linux线程函数原型是这样的: void* thread_fun(void* arg) 它的返回值是 空类型指针,入口参数也是 空类型指针.那么线程的 exit code 也应该是 void * 类 ...

  2. [原]unity中WWW isDone方法只能在主线程中调用

    项目中要使用动态加载,原计划是生成WWW对象后,放到一个容器里.由一个独立线程轮询容器里的对象,如果www.isDone为true时,回调一个接口把结果交给请求方. new Thread( new T ...

  3. 主线程中也不绝对安全的 UI 操作

    从最初开始学习 iOS 的时候,我们就被告知 UI 操作一定要放在主线程进行.这是因为 UIKit 的方法不是线程安全的,保证线程安全需要极大的开销.那么问题来了,在主线程中进行 UI 操作一定是安全 ...

  4. 用Handler的post()方法来传递线程中的代码段到主线程中执行

    自定义的线程中是不能更新UI的,但是如果遇到更新UI的事情,我们可以用handler的post()方法来将更新UI的方法体,直接传送到主线程中,这样就能直接更新UI了.Handler的post()方法 ...

  5. android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法

    MONO 调用一个线程操作UI 然后报Only the original thread that created a view hierarchy can touch its views.错误 goo ...

  6. Android中,子线程使用主线程中的组件出现问题的解决方法

    Android中,主线程中的组件,不能被子线程调用,否则就会出现异常. 这里所使用的方法就是利用Handler类中的Callback(),接受线程中的Message类发来的消息,然后把所要在线程中执行 ...

  7. httpUrlConnection连接网络的用法(用到了handle传递消息,在主线程中更新UI)

    由于httpclient在Android5.0以后已经过时,所以官方推荐使用httpUrlConnection来连接网络,现将该连接的基本方法展示,如下 注意:记得加入<uses-permiss ...

  8. 在非主线程中更新UI

    在非主线程中调用了showMessage方法,结果报错:Can't create handler inside thread that has not called Looper.prepare() ...

  9. Java线程和多线程(四)——主线程中的异常

    作为Java的开发者,在运行程序的时候会碰到主线程抛异常的情况.如果开发者使用Java的IDE比如Eclipse或者Intellij IDEA的话,可能是不需要直接面对这个问提的,因为IDE会处理运行 ...

随机推荐

  1. JAVA数据结构--Array数组实现

    所谓数组,是有序的元素序列. [1]  若将有限个类型相同的变量的集合命名,那么这个名称为数组名.组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量.用于区分数组的各个元素的数字编 ...

  2. HDU - 6096 处理后缀的字典树

    题意:给定n个字符串,m次询问,每次询问多少个字符串前缀是pre且后缀是suf,前后缀不可相交 字典树同时存储前后缀,假设字符串长为len则更新2*len个节点,依次按s[0],s[len-1],s[ ...

  3. [中英对照]User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序

    如对Linux用户态驱动程序开发有兴趣,请阅读本文,否则请飘过. User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序 ...

  4. 有符号整数比较v.s.无符号整数比较

    本文尝试从汇编的角度给出有符号整数比较与无符号整数比较的区别所在. 在<深入理解计算机系统>(英文版第二版)一书中的Page#77,有下面一个练习题: 将上述示例代码写入foo1.c文件, ...

  5. Group by、having、order by、Distinct 使用注意事项

    直奔主题,如下SQL语句 SELECT COUNT(*) AS COUNT,REQUEST,METHOD FROM REQUESTMETH GROUP BY REQUEST,METHOD HAVING ...

  6. 【扫盲】】32位和64位Windows的区别

    用户购买windows安装盘或者重新安装操作系统的时候,通常会遇到这个问题,就是不知道该如何选择使用32位操作系统和64位操作系统,有人说64位系统速度快,其实理论上确实是这样,不过具体还要根据你的个 ...

  7. [PY3]——IO——文件读写

    文件打开和关闭 # 使用open 打开文件,返回时值是一个 File-like对象 f.open('/test/file') # 使用read读取文件 f.read( ) # 使用close关闭文件 ...

  8. 【AppScan】入门工作原理详解

    AppScan,即 AppScan standard edition.其安装在 Windows 操作系统上,可以对网站等 Web 应用进行自动化的应用安全扫描和测试.Rational AppScan( ...

  9. scala笔记,主要摘自网络教程

    1.scala是一种纯面向对象的语言,每个值都是对象.对象的数据类型以及行为由类和特质描述 2.类的扩展有2种机制:继承和混入机制 3.scala是一种函数式语言,其函数也能当成值来使用 ==4.sc ...

  10. PHP学习1——快速入门

    主要内容: 搭建PHP开发环境 第一个helloworld程序 PHP(Hypertext Preprocessor)PHP超文本预处理程序,是一种嵌入HTML的脚本语言,运行在服务器. 搭建PHP开 ...