使用同步对象避免多线程退出时内存泄露

前面的文章,我提到了有关两个或两个以上的界面线程同时运行的时候,我们必须要将除了主界面窗口对象以外的附窗口对象要首先销毁,删除,主窗口再退出,这样,可以避免因为窗口对象没有被删除造成的内存泄露,有一种情况,很简单,就是别的线程的窗口运行完成任务之后我们手动关闭,那么不会有什么问题,但是有时候我们要求两个或是多个线程的窗口同时存在,我们要求,我们在主窗口点击关闭的时候,要求先关闭别的线程的窗口,最后关闭主窗口,这个时候,我们必须要使用到同步对象来实现,在主窗口中使用等待函数,等待所有的别的窗口都关闭之后,在关闭主窗口,这么一来,就可以避免因来不及销毁别的线程的窗口对象造成内存泄露。

但是这个时候,又有一个问题出现了,我们在何时调用呢,要知道我们窗口对象的外部调用DestroyWindow是无效的,我们必须在对象内部的执行函数中调用,如下图所示:

void CDlg::OnCancel()
{
// TODO: 在此添加专用代码和/或调用基类
this->DestroyWindow();
//CDialogEx::OnCancel();
}

只有这样,才会生效,执行销毁窗口的任务,并且发送WM_DESTROY消息。而且在出窗口中我们的等待函数应该何处执行等待呢。通过对windows程序结束以及最后几个消息的的顺序的意义,我们可以这么做。首先我们在app类的初始化函数中我们创建一个同步对象,并作为其成员变量,当然,你可以用c++类,或是使用sdk的同步对象句柄,都可以,为什么要在app类中,主要是对象的传递问题,这个是有关mfc全局对象的问题,这里不做阐述,网上很多。如下:

InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
hEvent=::CreateEvent(NULL,TRUE,FALSE,L"DLG");/创建同步对象
AfxEnableControlContainer();

然后我们在子线程的这个地方调用函数,设置同步对象有信号,我这里用的sdk中的句柄的形式,如下:

void CDlg::PostNcDestroy()
{
// TODO: 在此添加专用代码和/或调用基类
delete this;
::SetEvent(((CdlgtestApp*)AfxGetApp())->hEvent);//设置为有信号
CDialogEx::PostNcDestroy();
}为什么要在这里呢,因为这个是窗口对象销毁的时候的最后一个调用的函数。

然后在主窗口的WM_CLOSE消息中发送一个关闭消息到附窗口

void CdlgtestDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
::SendMessage(hWnd,WM_CLOSE,0,0);
WaitForSingleObject(((CdlgtestApp*)AfxGetApp())->hEvent,10000);
CloseHandle(((CdlgtestApp*)AfxGetApp())->hEvent);
CDialogEx::OnClose();
}

为什么呢,因为这个消息是在响应窗口的关闭操作,这是在开始关闭操作执行之前的一个消息,这个消息过后,如果对话框,会调用OnCancel关闭对话框,或如果是普通窗口,就应该在这里执行DestoryWindow的命令,或是有的就不关闭,而是执行最小化的操作。也就说这个是执行各种命令之前我们可以执行别的操作。在这里我们发送了一个WM_CLOSE消息给附窗口,执行关闭操作,同时在等待关闭的操作完成之后,关闭主窗口。

这样一来,我们就其实就是完全准照了windows的程序的标准推出方法退出各个界面线程。当然,如果是工作线程,就更加简单了。因为不会设计到窗口对象的销毁问题,而是直接等待过程函数的执行完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值