您的位置:首页 > 其它

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

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

但是这个时候,又有一个问题出现了,我们在何时调用呢,要知道我们窗口对象的外部调用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的程序的标准推出方法退出各个界面线程。当然,如果是工作线程,就更加简单了。因为不会设计到窗口对象的销毁问题,而是直接等待过程函数的执行完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐