在项目工程中,我们可能会使用第三方开发的模块。该模块提供一个接口用于完成非常复杂和耗时的工作。我们一般不会将该API放在UI线程中执行,而是启动一个线程,用工作线程去执行这个耗时的操作。(转载请指明出于breaksoftware的csdn博客)

static VOID OtherPartFun() // 第三方提供函数,超级耗时,不如来个极限,死循环
{int nIndex = 0;while ( true ) {nIndex++;printf("%d\n",nIndex);Sleep( ONESECOND );}
}
// 我们启动的线程函数,用于在工作线程中执行那个耗时的第三方提供函数
static DWORD WINAPI ThreadRoutine(LPVOID lpParam)
{OtherPartFun();return 0;
}

以上方法很好解决了不堵塞关键线程的目的。但是问题永远不会间断。比如当我们在某些条件下,我们要终止该线程的执行。如何做呢?

一是让该模块设计方提供一个终止线程接口,比如给我们一个事件,我们通过设置这个事件来通知该线程退出。

static VOID OtherPartFun()
{int nIndex = 0;while ( WAIT_OBJECT_0 != WaitForSingleObject( g_ExitEvent, 1000)  ) {nIndex++;printf("%d\n",nIndex);Sleep( ONESECOND );}
}

另一种可能就是TerminateThread。

如果方案1对方不提供, 你也无法接受方案二导致的资源未释放。那有如何办呢?

目前有个方案是使用SEH。我们刻意造成该线程产生异常,同时在函数中捕获该异常,以使得线程可以体面的退出。

以下我详细讲解下这个方案。

1 线程函数加上SEH捕获异常。这样我们认为制造异常后,不会导致进程出问题。

static DWORD WINAPI ThreadRoutine(LPVOID lpParam)
{__try {OtherPartFun();  // 第三方的耗时函数,我们用__try包住它。}__except(EXCEPTION_EXECUTE_HANDLER) {printf("Except!Thread will exit.\n"); // 我们认为触发异常后会进入该逻辑。}return 0;
}

2 设置异常。我们设置异常的大体思路是

        A 挂起线程

         B 获取线程EIP

         C 修改线程EIP为违例地址

         D 恢复线程

我们看下代码

    HANDLE hThread = NULL;hThread = CreateThread( NULL, 0, ThreadRoutine, NULL, 0, NULL ); // 创建线程Sleep( 2 * ONESECOND ); // 模拟做点事情SuspendThread(hThread); // 挂起线程CONTEXT ThreadContext;ThreadContext.ContextFlags = CONTEXT_CONTROL; // 设置要获取EIP寄存器GetThreadContext( hThread, &ThreadContext );  // 获取EIP寄存器 ThreadContext.Eip = NULL;                     // 将EIP寄存器改成违例地址,这样在恢复线程执行后,线程会适时抛出异常SetThreadContext(hThread , &ThreadContext);   // 保存EIPResumeThread(hThread);                        // 恢复线程,线程即将退出Sleep( 15 * ONESECOND );if ( NULL != hThread ) {CloseHandle(hThread);hThread = NULL;}

我们看下执行结果


        可以发现,我们线程“体面”的退出了。

其实这个方案也是存在不完善的地方的。比如我们线程产生了死锁等,线程将进入内核态等待。这个时候我们获取的EIP是客户态函数的着陆点。而我们此时去修改EIP,还是要等待线程从内核态返回后才能触发异常。

提供下该例子的工程

一种不会导致资源泄露的“终止”线程的方法相关推荐

  1. android的内存泄露有几种,Android中几种有可能会导致内存泄露的情况

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 1.Static静态成员导致的内存泄露 将占用大量内存空间的变量声明为static静态类型.当Activity被销毁的时 ...

  2. 什么是内存溢出与内存泄露,几种常见导致内存泄露的写法

    最近朋友推荐了一篇关于内存溢出与内存泄漏的文章,感觉写的还不错,于是便在网上搜索了一番,对这块进行了加固,发现自己之前写的代码也存在一些内存泄漏的风险,所以弄懂内存泄漏与内存溢出是很有利于我们提高代码 ...

  3. layout-v17 导致资源 替换不全,替换不成功

    2021.1.18 记录问题 android 重新分包过程中遇到资源无法替换问题,所有图片资源和布局资源都放进去了,分包后却无法替apk中的资源,查找了很久才发现,母包中有layout-v17文件,里 ...

  4. 终止线程的2种方法。标记法和中断

    引言 在原来的jdk版本中: 提供了暂停,恢复,终止线程的方法,分别是suspend(),resume(),stop(); 但是它们都存在缺陷,比如暂停suspend()方法在调用后,线程不会释放资源 ...

  5. 迭代终止准则的三种形式_一种经验模态分解筛选迭代过程终止准则的方法与流程...

    本发明属于数据分析技术领域,涉及筛选迭代余量的相对方差作为经验模态分解方法筛选迭代过程的终止准则. 背景技术: 一维的Fourier分解.小波分析,二维的PCA/EOF等方法,都是从低频开始分解,获取 ...

  6. pthread_create会导致内存泄露

    这几天一直在调试一个系统,系统的功能就是定时发送数据.接收数据然后解析收到的数据,转换成一定的格式存入数据库中.我为了并发操作,所以每接收到一个数据包,就调用pthread_create函数创建一个默 ...

  7. java 关闭句柄_191206_01 Java中的句柄与资源泄露

    Java中的句柄与资源泄露 本文内容介绍Java中的句柄与资源泄露问题,是Java网站开发中必须清楚掌握的基本概念.句柄包括两类:文件句柄和网络句柄.本文是Java学习指南系列教程的官方配套文档,配套 ...

  8. android开发中,可能会导致内存泄露的问题

    转自 : http://spencer-dev.lofter.com/post/d7b9e_6faf120 在android编码中,会有一些简便的写法和编码习惯,会导致我们的代码有很多内存泄露的问题. ...

  9. inputstreamreader未关闭会导致oom_ThreadLocal 一定会导致内存泄露?

    在面试的时候,ThreadLocal作为高并发常用工具经常会被问到.而面试官比较喜欢问的问题有以下两个: 1.ThreadLocal是怎么实现来保证每个线程的变量副本的. 2.ThreadLocal的 ...

最新文章

  1. 杨学海:跨境电商新通道-进口保税直邮模式解析
  2. 用svg实现一个环形进度条
  3. 如何将表中的数据导出到电子表格中
  4. 自定义异常时exception is never thrown in the corresponding try block和unhandled exception
  5. Groovy新手教程
  6. iptables第一部分
  7. PHP(ThinkPHP5.0) + PHPMailer 进行邮箱发送验证码
  8. 关于LED 流水灯的软件调试方法(非开发板调试)
  9. 聚类分析matlab算例,应用Matlab聚类方法分析大坝监测资料
  10. CNN--MINIST
  11. 0基础自学鸿蒙-Day_002 HelloWorld
  12. 高数——换元法(2)
  13. 人造的风景 --- 东部华侨城一日游感想与收获
  14. Python开发就业岗位有哪些?Python薪资待遇如何?
  15. mosquitto教程(三)开启服务器及客户端发布和订阅
  16. strictmath_Java StrictMath cosh()方法与示例
  17. 024空格沙悟净死亡
  18. lintel安装成功记与血泪史
  19. 覆盖桌面壁纸类似现在的一些桌面壁纸软件包括换HTML壁纸功能
  20. Mac专业屏幕录像软件:RecordAnyVID

热门文章

  1. QT:qt安装缺少GUI Application 选项
  2. STM32电源框图解析(VDD、VSS、VDDA、VSSA、VREF+、VREF-、VBAT等的区别)
  3. 图像形态学(opencv),运行后通过在屏幕上输入对应指令完成相对应的形态学方法。
  4. blazeface学习笔记
  5. 编译OpenCV 2+ with CUDA 9+
  6. C++中模板template typename T
  7. Ubuntu 14.04 64位安装深度音乐和深度影音
  8. Python中完整的机器学习数据科学课程
  9. +z +Z compiler flag for HP
  10. HashMap 和 Hashtable 的 6 个区别,最后一个没几个人知道!