博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何正确的关闭 MFC 线程
阅读量:4694 次
发布时间:2019-06-09

本文共 2779 字,大约阅读时间需要 9 分钟。

.关于MFC的线程

  1.MFC的线程有两种,一种称为Work线程,一种称为UI线程。一般情况下Work线程与UI线程的区别主要在于UI线程有消息队列(并不是有没有界面,这点要注意,UI线程也是可以没有界面的)。

  2.创建这两种线程的区别也不大,可以从创建函数看出。

1.	// Work线程   2.	CWinThread* AfxBeginThread(  3.	      AFX_THREADPROC pfnThreadProc,  4.	      LPVOID pParam,  5.	      int nPriority = THREAD_PRIORITY_NORMAL,  6.	      UINT nStackSize = 0,  7.	      DWORD dwCreateFlags = 0,  8.	      LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  9.	     );  10.	  11.	// UI线程   12.	CWinThread* AfxBeginThread(  13.	      CRuntimeClass* pThreadClass,  14.	      int nPriority = THREAD_PRIORITY_NORMAL,  15.	      UINT nStackSize = 0,  16.	      DWORD dwCreateFlags = 0,  17.	      LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  18.	     );

. 结束线程前的注意事项

  在结束一个线程前,只有一点要注意,那就是m_bAutoDelete 的状态。(什么?不知道m_bAutoDelete ?!!快去查阅MSDN吧)。

  m_bAutoDelete = FALSE;// 表示你自己管理 CWind 对象,包括它的清理   

  m_bAutoDelete = TRUE;  // 默认值, 系统会自己清理 CWind 对象  

当然还包括CloseHandle()ExitInstance()等等一堆函数的调用。

m_bAutoDelete = FALSE; 那么就一定要记得自己在用完后调用delete删除创建线程的对象,这一点极为重要,因为不调用delete一定会有内存泄漏问题

.正确的结束一个Work线程

  因为Work线程是一个全局函数,或者是一个Static函数,所以它的运行完成也就是它的正常退出了。(什么?不明白,示例代码如下)

  1.情况一:

1.	UINT WorkFunc(LPVOID pParam)  2.	{  3.	  // 工作   4.	  ......  5.	   return 0;  // 就算正常退出了,简单吧   6.	}

.情况二:

Work线程是个死循环或一时半会儿出不来,这时要主线程要发个消息给Work线程,让他退出。

1.	UINT WorkFunc(LPVOID pParam)  2.	{  3.	  for(;;)  4.	  {  5.	   // ...   6.	  if( WAIT_OBJECT_0 == WaitForSingleObject(m_hThread, INFINITE)} // 收到激发态的消息   7.	    {  8.	      return 0;//正常退出   9.	     }  10.	  11.	 }//end for   12.	    13.	 return 0;  14.	}
关于主线程发一个激发态的消息给
Work
线程,有多种方法,如在主线程里调用
SetEvent()
等等,你想用什么都行,但是最好不要在
Work
线程里用
Busy loop
的方法。

.正确结束一个UI线程

  因为UI线程有消息队列,所以结束一个UI线程最好的方法是发一个WM_QUIT消息给消息队列,方法很多如:PostQuitMessage(),PostThreadMessage()等等。但是发出消息后最好等待看UI线程是否已经退出(很多人都没有提及这一点,但是实际工作中发现,加上这一点是多么的重要)

1.	// 主线程结束UI线程的代码   2.	if(pThread)   3.	{  4.	  // 1. 发一个WM_QUIT 消息结 UI 线程   5.	  pThread->PostThreadMessage(WM_QUIT, NULL, NULL);  6.	                  7.	 // 2. 等待 UI 线程正常退出   8.	 if (WAIT_OBJECT_0 == WaitForSingleObject(pThread->m_hThread, INFINITE))  9.	 {  10.	    // 3. 删除 UI 线程对象,只有当你设置了m_bAutoDelete = FALSE; 时才调用   11.	  delete   pThread;   12.	 }  13.	  14.	}

.关于几个问题的解答

.问:为什么我的UI线程没有调用ExitInstance()

答:最大的可能是你的WM_QUIT消息没有通知到UI线程。为了保险期间最好调用PostThreadMessage(),这样可以指定线程的ID。当然如果你对消息比较熟悉的话,也可以抛一个消息到最顶层。

 

.问:为什么我的UI线程没有调用析构函数?

答:检查看你的m_bAutoDelete =FALSE,如果是的话,那么看你的线程对象是否已经delete了。一般情况下调用delete会调用析构函数

 

.问:在UI线程中没有调用WaitForSingleObject(),会怎么样?

答:我们知道在PostMessage()之后,函数会马上返回,如查没有wait...(),那么紧接着就调用了delete很有可能对象做的退出操作过程还没有完成时,又把对象delete掉了,结果还是没有正常结束。(注:WM_QUIT消息之后会触发一堆函数,这个时间是不定的,所以最好Wait...才是正道。)

 

.最后不愿提的函数

几乎每本讲线程的书都会提到下面的函数:

  void AfxEndThread(UINT nExitCode);

  TerminateThread();

......还有其它的一些极端的函数,建议:不要用!!

转载于:https://www.cnblogs.com/young525/p/5873845.html

你可能感兴趣的文章
端口扫描base
查看>>
iOS IM开发的一些开源、框架和教程等资料
查看>>
FansUnion:共同写博客计划终究还是“流产”了
查看>>
python 二维字典
查看>>
pip 警告!The default format will switch to columns in the future
查看>>
Arrays类学习笔记
查看>>
实验吧之【天下武功唯快不破】
查看>>
2019-3-25多线程的同步与互斥(互斥锁、条件变量、读写锁、自旋锁、信号量)...
查看>>
win7-64 mysql的安装
查看>>
dcm4chee 修改默认(0002,0013) ImplementationVersionName
查看>>
maven3在eclipse3.4.2中创建java web项目
查看>>
发布时间 sql语句
查看>>
黑马程序员 ExecuteReader执行查询
查看>>
记一些从数学和程序设计中体会到的思想
查看>>
题目1462:两船载物问题
查看>>
POJ 2378 Tree Cutting(树形DP,水)
查看>>
第二冲刺阶段个人博客5
查看>>
UVA 116 Unidirectional TSP (白书dp)
查看>>
第三方测速工具
查看>>
MySQL 网络访问连接
查看>>