peakzhang 发表于 2007-12-17 23:08:43

如何正确退出rector ?

mfc ace 5.5

已经能够正确接受数据,单独开了个线程跑ACE_Reactor::instance()->run_reactor_event_loop();

UINT ThreadReactor(LPVOID param)
{
    int result = ACE_Reactor::instance()->run_reactor_event_loop();
    return 0;
}

void CAceTestDlg::OnButServer()
{
    //*ACE_WFMO_Reactor 默认方式
    ACE_INET_Addr port_listen(9000);
    m_ClientAcceptor.reactor(ACE_Reactor::instance());
    if(m_ClientAcceptor.open(port_listen) == -1)
      return ;
    AfxBeginThread(ThreadReactor,NULL);
}

在dia里执行end_reactor_event_loop(),也可以成功结束上面
ThreadReactor 线程。

void CAceTestDlg::OnButtonClose()
{
    // TODO: Add your control notification handler code here
    ACE_Reactor::instance()->end_reactor_event_loop();
}


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

出错位置

ClientAcceptor::~ClientAcceptor()
{
    reactor()->remove_handler(ACE_INVALID_HANDLE,0);
}

peakzhang 发表于 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();

}
不解!

peakzhang 发表于 2007-12-17 23:09:02

追踪到
    ACE_Framework_Repository::close_singleton ();

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

如何解决?

peakzhang 发表于 2007-12-17 23:09:08

没有正确的进行线程同步,你必须等待ThreadReactor正常退出后,再执行关闭操作。

这类问题是使用ACE经常碰见的问题了。可以用WaitForSingleObject来处理,或者用ACE_Task来处理。

peakzhang 发表于 2007-12-17 23:09:14

ThreadReactor 的确是正常退出的.
    end_reactor_event_loop 后   run_reactor_event_loop 返回0

peakzhang 发表于 2007-12-17 23:09:20

不这么认为,你确定那个线程退出了吗?

或者检查其它线程同步代码吧。

peakzhang 发表于 2007-12-17 23:09:27

哦,确定退出了.

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

那里可以把代码传上去?

peakzhang 发表于 2007-12-17 23:09:49

只开了一个线程

UINT ThreadReactor(LPVOID param)
{
    ACE_INET_Addr port_listen(1515);
    ClientAcceptor ClientAcceptor;
    ClientAcceptor.reactor(ACE_Reactor::instance());
    if(ClientAcceptor.open(port_listen) == -1)
      return -1;
    int result = ACE_Reactor::instance()->run_reactor_event_loop();
    return result;
}
//启动线程
void CAceTestDlg::OnButServer()
{
    AfxBeginThread(ThreadReactor,NULL);
}

//这里停止
void CAceTestDlg::OnButtonClose()
{
    // TODO: Add your control notification handler code here
    ACE_Reactor::instance()->end_reactor_event_loop();
}

//这里析构,略:在initDialog 里 ACE::init()
BOOL CAceTestDlg::DestroyWindow()
{
    // TODO: Add your specialized code here and/or call the base class
    ACE_Reactor::instance()->owner(ACE_OS::thr_self());
    ACE::fini();      
    return CDialog::DestroyWindow();
}

//Acceptor 的 handle_close
int ClientAcceptor::handle_close(ACE_HANDLE handle,ACE_Reactor_Mask close_mask)
{
    if( acceptor_.get_handle()!= ACE_INVALID_HANDLE)
    {
      ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK|
            ACE_Event_Handler::DONT_CALL;
      reactor()->remove_handler(this,m);
      acceptor_.close();
    }
    return 0;
}
//ClientService的 handle_close
int ClientService::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
{
    if( ACE_Event_Handler::WRITE_MASK == close_mask)
      return 0;
    close_mask = ACE_Event_Handler::ALL_EVENTS_MASK|ACE_Event_Handler::DONT_CALL;
    reactor()->remove_handler(this,close_mask);
    sock_.close();
    output_queue_.flush();
    delete this;
    return 0;
}

注:
    除了开个线程,其他均为抄书.

peakzhang 发表于 2007-12-17 23:09:56

线程同步处理有问题,

UINT ThreadReactor(LPVOID param)
在你void CAceTestDlg::OnButtonClose()
后,不能保证立刻返回并且退出。同样,ClientService::handle_close也不能,这就是多线程抢占的特性。你必须等待额外的处理线程退出,光debug是没用的,多线程程序和网络程序有某种程度的不可调试性。
不信你在ACE::fini(); 前等待2秒钟试试。Sleep(2000);

peakzhang 发表于 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);根本没必要,不过还是测试了一下,呵呵。没有反应
页: [1] 2
查看完整版本: 如何正确退出rector ?