C++ Boost asio:io服务在销毁步骤中被阻止更多处理程序故障

C++ Boost asio:io服务在销毁步骤中被阻止更多处理程序故障,c++,multithreading,boost,boost-asio,C++,Multithreading,Boost,Boost Asio,为了管理tcp通信,我在VisualStudio10上使用BoostASIO版本1.48和x64项目设置以及sdk 7.1和windows 7 我设计了一个包含内部成员的类: asio服务 asio tcp ipv4套接字 阿西奥街 已接收消息的列表 指向boost线程的指针 在调试运行时期间,进程将执行以下步骤: 构造对象和内部属性io服务、套接字、串 和指向线程的指针 使用创建的套接字创建异步连接 通过异步读取侦听消息头 创建一个调用io服务运行的线程 头消息被读取,监听在串中调用的消息

为了管理tcp通信,我在VisualStudio10上使用BoostASIO版本1.48和x64项目设置以及sdk 7.1和windows 7

我设计了一个包含内部成员的类:

  • asio服务
  • asio tcp ipv4套接字
  • 阿西奥街
  • 已接收消息的列表
  • 指向boost线程的指针
在调试运行时期间,进程将执行以下步骤:

  • 构造对象和内部属性io服务、套接字、串 和指向线程的指针
  • 使用创建的套接字创建异步连接
  • 通过异步读取侦听消息头
  • 创建一个调用io服务运行的线程
  • 头消息被读取,监听在串中调用的消息体 使用异步读取
  • 通过post函数在IOservice中堆叠消息和调用处理 还有一个训练员
  • 通过异步读取侦听消息头
  • 重复n时间步骤5至7
  • 取消,然后关闭插座
  • 停止并重置io服务
  • 销毁该对象
  • 我有两大问题:

    =>从未调用连接处理程序,但连接已完成! 处理函数:=

    void CManager::HandleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it)
    
    =>销毁文件boost\asio\detail\impl\win\u iocp\u io\u service.ipp l358中的进程程序块期间:

    BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
            &completion_key, &overlapped, block ? gqcs_timeout : 0);
    
    我不明白为什么

    编辑:

    我的代码:

    请注意,我最糟糕的问题是在销毁msgManager实例期间出现程序块

    致以最良好的祝愿

    CManager::CManager(const char* _ipAdress, const char* _port):    
        m_MsgFactory(),
        m_IOService(),
        m_Socket(m_IOService),
        m_Strand(m_IOService),
        m_ReceivedMsgs(),
        m_pThread(nullptr)
    {
        Start( _ipAdress, _port);
    }
    
    CManager::~CManager(void)
    {
    }
    
    CManager::TThread* CManager::GetThread(void)
    {
        return m_pThread;
    }
    
    void CManager::Start(const char* _ipAdress, const char* _port)
    {
        CreateConnection( _ipAdress, _port);
    
        if(nullptr == m_pThread)
        {
            m_pThread = new TThread( boost::bind(&boost::asio::io_service::run,&m_IOService) );
        }
    }
    
    void CManager::Stop()
    {
        CloseConnection();
    
        m_IOService.stop();
        m_IOService.reset();
    }
    
    void CManager::CreateConnection(const char* _ipAdress, const char* _port)
    {
        boost::asio::ip::tcp::resolver resolver(m_IOService);
    
        boost::asio::ip::tcp::resolver::query query( boost::asio::ip::tcp::v4(), std::string(_ipAdress), std::string(_port) );
        boost::asio::ip::tcp::resolver::iterator endPointIt = resolver.resolve(query);
    
        // Start an asynchronous connect operation.
        boost::asio::async_connect(m_Socket, endPointIt, boost::bind(&CManager::HandleConnect, this, boost::asio::placeholders::error, endPointIt));
    
        //Previous handler is never called. Without next code, asio log in consol show a cancel message !
        Listen();
    }
    
    void CManager::HandleConnect(const boost::asio::placeholders::error& error, TResolver::iterator it)
    {
        if (!error)
        {
            Listen();
        }
    }
    
    void CManager::CloseConnection()
    {
        m_Socket.cancel();
        m_Socket.close();
    }
    
    void CManager::Listen(void)
    {
            TMsgPtr pMsg(new TMsg());
    
            CMsgBase::TMsgBuffer headerBuffer;
            if(!pMsg->GetHeaderBuffer(headerBuffer))
            {            
                return;
            }
    
            boost::asio::async_read(m_Socket,
                                    headerBuffer,
                                    m_Strand.wrap( boost::bind(&CManager::HandleReadMsg, this, boost::asio::placeholders::error, pMsg) ) );        
    }
    
    void CManager::HandleReadMsg(const boost::asio::placeholders::error& error, TMsgPtr _pMsgBase )
    {
        if (!error && nullptr != _pMsgBase &&  true == _pMsgBase->HasBody() )
        {
            CMsgBase::TMsgBuffer       bodyBuffer;
            _pMsgBase->GetBodyBuffer( bodyBuffer );
    
            //Next treatment.
            boost::asio::async_read(m_Socket,
                                    bodyBuffer,
                                    m_Strand.wrap( boost::bind(&CManager::HandleMsg, this, boost::asio::placeholders::error, _pMsgBase) ) );
        }
        else
        {
            Listen();
        }
    }
    
    void CManager::HandleMsg(const boost::asio::placeholders::error& error, TMsgPtr _pMsgBase )
    {
        if (!error && nullptr != _pMsgBase)
        {
            m_ReceivedMsgs.push_back( _pMsgBase );
    
            //post will not call the function directly but postpone the call in io service.
            m_IOService.post( boost::bind(&CManager::TranslateMsg, this) );
        }
    
        //Still listen for next messages.
        Listen();
    }
    
    int _tmain(int argc, char* argv[])
    {
        try
        {
            /*Some code*/
    
            boost::thread_group threadGroup;
    
            CManager msgManager( ipAddress, ipPort );
            threadGroup.add_thread( msgManager.GetThread() );
    
            /*Some code*/
    
            msgManager.Stop();
            threadGroup.join_all();
    
            /*Some code*/
        }
        catch (std::exception& e)
        {
            /*Some code*/
        }
    
        return 0;
    }
    

    这似乎是您发布到
    io_服务
    的对象在
    io_服务
    队列中仍处于挂起状态时被销毁的终身问题


    您应该确保为所有可能包含对已创建对象的引用的处理程序提供执行的机会。我注意到您将处理程序绑定到
    CManager
    的指针,这意味着为了安全起见,您应该让所有绑定到
    CManager
    实例的处理程序在该
    CManager
    实例被销毁之前执行(成功或有错误)。

    我们不理解为什么这样做。看到处理程序的声明不是很有用,我们需要看到如何“调用”它(如何将该处理程序传递给
    async\u connect()
    )。此外,还有很多事情会导致现有排队操作阻塞。我们需要看到更多的代码来有效地提供帮助。我在问题中添加了我的代码。谢谢你的回答。事实上,我希望在应用程序运行时收听新消息。所以,我总是在消息反序列化结束时调用listen函数。如果我理解你的答案,如果这个处理器没有被执行,我就不能销毁我的对象。有更好的模式可以遵循吗?致以最诚挚的问候。
    io_service::run
    功能将继续运行,直到没有更多工作要做。如果关闭套接字,则将取消所有挂起的IO操作。一旦执行了所有挂起的处理程序,那么
    io_service::run
    函数应该返回。在那个时候,销毁您的对象可能是安全的。使用
    boost::asio
    进行生命周期管理可能会很复杂。