找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 8322|回复: 14

如何正确退出rector ?

[复制链接]
发表于 2007-12-17 23:08:43 | 显示全部楼层 |阅读模式
mfc ace 5.5

已经能够正确接受数据,单独开了个线程跑ACE_Reactor::instance()->run_reactor_event_loop();
  1. UINT ThreadReactor(LPVOID param)
  2. {
  3.     int result = ACE_Reactor::instance()->run_reactor_event_loop();
  4.     return 0;
  5. }
  6. void CAceTestDlg::OnButServer()
  7. {
  8.     //*  ACE_WFMO_Reactor 默认方式
  9.     ACE_INET_Addr port_listen(9000);
  10.     m_ClientAcceptor.reactor(ACE_Reactor::instance());
  11.     if(m_ClientAcceptor.open(port_listen) == -1)
  12.         return ;
  13.     AfxBeginThread(ThreadReactor,NULL);
  14. }
复制代码
在dia里执行end_reactor_event_loop(),也可以成功结束上面
ThreadReactor 线程。
  1. void CAceTestDlg::OnButtonClose()
  2. {
  3.     // TODO: Add your control notification handler code here
  4.     ACE_Reactor::instance()->end_reactor_event_loop();
  5. }
复制代码

问题1 为何ThreadReactor结束后,仍能在客户端Connect ?
问题2 如何正确退出,不引发错误 ?

出错位置
  1. ClientAcceptor::~ClientAcceptor()
  2. {
  3.     reactor()->remove_handler(ACE_INVALID_HANDLE,0);
  4. }
复制代码
 楼主| 发表于 2007-12-17 23:08:52 | 显示全部楼层
附注:
      先前代码是因为ClientAcceptor析构在ACE::fini()之后

       修改后,发现 ACE::fini() 依然错误
void CAceTestDlg::OnClose()
{
    // TODO: Add your message handler code here and/or call default
    ACE_Reactor::instance()->owner(ACE_OS::thr_self());
    ACE::fini();
    CDialog::OnClose();

}
不解!
 楼主| 发表于 2007-12-17 23:09:02 | 显示全部楼层
追踪到
    ACE_Framework_Repository::close_singleton ();

发生错误,系内部 delete ACE_Framework_Repository::repository_; 出错

如何解决?
 楼主| 发表于 2007-12-17 23:09:08 | 显示全部楼层
没有正确的进行线程同步,你必须等待ThreadReactor正常退出后,再执行关闭操作。

这类问题是使用ACE经常碰见的问题了。可以用WaitForSingleObject来处理,或者用ACE_Task来处理。
 楼主| 发表于 2007-12-17 23:09:14 | 显示全部楼层
ThreadReactor 的确是正常退出的.
    end_reactor_event_loop 后     run_reactor_event_loop 返回0
 楼主| 发表于 2007-12-17 23:09:20 | 显示全部楼层
不这么认为,你确定那个线程退出了吗?

或者检查其它线程同步代码吧。
 楼主| 发表于 2007-12-17 23:09:27 | 显示全部楼层
哦,确定退出了.

因为是在手工测试,其他地方没有线程同步的地方.

那里可以把代码传上去?
 楼主| 发表于 2007-12-17 23:09:49 | 显示全部楼层
只开了一个线程
  1. UINT ThreadReactor(LPVOID param)
  2. {
  3.     ACE_INET_Addr port_listen(1515);
  4.     ClientAcceptor ClientAcceptor;
  5.     ClientAcceptor.reactor(ACE_Reactor::instance());
  6.     if(ClientAcceptor.open(port_listen) == -1)
  7.         return -1;
  8.     int result = ACE_Reactor::instance()->run_reactor_event_loop();
  9.     return result;
  10. }
  11. //启动线程
  12. void CAceTestDlg::OnButServer()
  13. {
  14.     AfxBeginThread(ThreadReactor,NULL);
  15. }
  16. //这里停止
  17. void CAceTestDlg::OnButtonClose()
  18. {
  19.     // TODO: Add your control notification handler code here
  20.     ACE_Reactor::instance()->end_reactor_event_loop();
  21. }
  22. //这里析构,略:在initDialog 里 ACE::init()
  23. BOOL CAceTestDlg::DestroyWindow()
  24. {
  25.     // TODO: Add your specialized code here and/or call the base class
  26.     ACE_Reactor::instance()->owner(ACE_OS::thr_self());
  27.     ACE::fini();        
  28.     return CDialog::DestroyWindow();
  29. }
  30. //Acceptor 的 handle_close
  31. int ClientAcceptor::handle_close(ACE_HANDLE handle,ACE_Reactor_Mask close_mask)
  32. {
  33.     if( acceptor_.get_handle()  != ACE_INVALID_HANDLE)
  34.     {
  35.         ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK|
  36.             ACE_Event_Handler::DONT_CALL;
  37.         reactor()->remove_handler(this,m);
  38.         acceptor_.close();
  39.     }
  40.     return 0;
  41. }
  42. //ClientService的 handle_close
  43. int ClientService::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
  44. {
  45.     if( ACE_Event_Handler::WRITE_MASK == close_mask)
  46.         return 0;
  47.     close_mask = ACE_Event_Handler::ALL_EVENTS_MASK|ACE_Event_Handler::DONT_CALL;
  48.     reactor()->remove_handler(this,close_mask);
  49.     sock_.close();
  50.     output_queue_.flush();
  51.     delete this;
  52.     return 0;
  53. }
复制代码
注:
    除了开个线程,其他均为抄书.
 楼主| 发表于 2007-12-17 23:09:56 | 显示全部楼层
线程同步处理有问题,

UINT ThreadReactor(LPVOID param)
在你void CAceTestDlg::OnButtonClose()
后,不能保证立刻返回并且退出。同样,ClientService::handle_close也不能,这就是多线程抢占的特性。你必须等待额外的处理线程退出,光debug是没用的,多线程程序和网络程序有某种程度的不可调试性。
不信你在ACE::fini(); 前等待2秒钟试试。Sleep(2000);
 楼主| 发表于 2007-12-17 23:10:18 | 显示全部楼层
To: winston
  
   void CAceTestDlg::OnButtonClose()  这个是mfc 的函数阿。
   作用是响应一个Button事件。
   在这个里面执行 end_reactor_event_loop 后,
   ThreadReactor就结束了

   ACE::fini();是在dia 的OnClose 事件中的,要手工关闭窗口才会执行。
   换而言之,关闭窗口ACE::fini()是在 ThreadReactor n久后的动作。

   Sleep(2000);根本没必要,不过还是测试了一下,呵呵。没有反应
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-23 13:22 , Processed in 0.025892 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表