多线程 DLL 回调函数问题,当应用程序退出时,有些操作并未完成,造成程序内存泄露,如何解决呢

问题描述如下:
  现在有一个DLL库,里面定义了一个线程,线程里面又调用了应用程序中定义的回调函数,这样当应用程序退出时,应用程序中的回调函数还没有执行完毕,停在中间了,造成程序内存泄露,Debug内存泄露,而Release直接报错。伪代码如下:
   
  Dll中定义个类B
  Class B{
  //类B里面定义了一个线程,如 
  CwinThread afxBeginThread(thread1,......)
  thread1()
  {
  while(flag)
  {
  callback();//应用程序A中的回调函数
  }
  }

  }


  应用程序如下定义A类:
  Class A{
  B *Ptr; //定义一个指向dll B类的指针,在构造函数中Ptr=new B(),然后就可以用Ptr调用A里面的成员函数了,在析构函数中delete B
  callback(...);
  }

  这样,当我关闭应用程序时,我在A类里面OnClose里面调用了Dll中的一个成员函数,将B类中线程函数的标志flag置为false;然后在关闭程序;就出现这个Bug问题了;

  分析定位如下:
  程序死在回调函数里面了,回调函数没有执行完毕,flag的标志改变了也没有用,因为程序已经死了,程序死的原因是A类已经析构了,所以A类中定义的B的指针对象的内存也析构了,Ptr就是一个错误的指针了,所以A类中callback没有顺利完成;造成以上的现象;
   
  现在我想请教大家,我想在A类中等待B类中的线程安全退出,即不死在中间,只要B的线程顺利执行,就会去判断flag标志,那么B的线程就顺利退出了,我的目的是让B的线程顺利退出后,A中的资源才被析构,换句话说,我想A中的回调函数callback 运行到末尾的时候,在析构A类中的资源,我想只有这样才能解决这个问题,不知道大家有什么好的办法吗;
   
  A中的无论用Sleep多少毫秒也不能解决这个问题;我开始想到在callback的最后也搞一个标志if (flag1){ SetEvent},然后采用事件,在OnClose函数里面waitforsingleObject,我想这样控制同步,但是也不能解决问题,困惑中,路过高手指点下。

 

 

 

解决方法如下:

      在论坛中发帖,高手帮忙解决了,解决方法如下:

     你的主线程结束不安全,主线程需要等待工作线程完全销毁时才能结束,但是你仅仅改变工作线程的flag是不行的。正如你这里面出的问题,工作线程还没有结束,OnClose响应后主线程已经返回了。
可以在主线程的OnClose或者OnDestory里面加入WaitForSingleObject,等待工作线程结束时其内核对象被signaled。但是这里面存在一个问题,如果你的回调函数里面有控件操作或者SendMessage之类的操作,这么做会造成死锁。如果是这种情况,你需要使用MsgWaitForMultipleObjects来手动消息泵,并且等待线程结束。
这里提供给你一个线程安全结束的函数,你可以把它用在自己工程里:
BOOL WaitForThreadEnd(HANDLE hEvent)
{
DWORD dwRet;
MSG msg;
while(1)
{
dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == WAIT_OBJECT_0)
{
return TRUE;
}
else if (dwRet == WAIT_OBJECT_0 + 1)
{
while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
return FALSE;
}
}
}

 

 

你的callback里有对picture的操作肯定会死锁了。
你的程序结构是:工作线程->callback->调用控件方法->发通知消息->等待主线程抓取消息并返回
这里如果使用WaitForSingleObject,因为主线程被阻塞,消息永远不能抓取,工作线程就不返回,死锁

WaitForThreadEnd提供了一种避免死锁的机制,既可以等待工作线程返回,又能实现消息循环。你所看到的那个while就是消息循环,它会不停泵出消息,好让callback成功完成对控件的操作并且返回。
这里面的HANDLE hEvent就是你的线程内核对象句柄,也就是pWorkThread->m_hThread。这里不需要你刻意置信号,因为当线程返回时因为引用计数归零,线程对象自动恢复为有信号的状态。
你可以把它放在DLL中封装成KillThread之类的供主线程调用。但是在B的析构里没用,它应该在程序A的OnClose或者OnDestory里,代替之前的WaitForSingleObject。

 

原帖链接:

http://topic.csdn.net/u/20110618/22/36ea27c0-8884-4633-958f-687b580c0565.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值