c++ - 如何删除boost io_service

标签 c++ boost

我的简化问题
我阅读了this thread,并试图删除io_service对象。我做这个

m_IO.stop();
m_IO.~io_service();

m_IO是boost::asio::io_service的对象。我发现我的线程被m_IO.~io_service();阻塞了如何删除io_service
我的完整问题
我通过使用boost io_service和截止时间计时器来设置每日计时器。问题是当我想删除我的每日计时器时,当我尝试删除boost io_service时,我的线程将消失。
main.cpp
int main()
{
    myDailyTimer* pTimer = new myDailyTimer;
    // do something
    delete pTimer;
    return 0;
}

我在myDailyTimer.cpp::int i = 0;myDailyTimer.cpp::int j = 0;main::return 0;中设置了断点。我的主线程可以达到int i = 0;,我的计时器线程不能达到int j = 0;,我的主线程不能达到return 0;
我发现我的主线程在尝试删除boost::asio::io_service对象时将消失。如何解决这个问题呢?我是否以错误的方式使用boost::asio::io_service
myDailyTimer.h
class myDailyTimerInterface
{
public:
    myDailyTimerInterface(){}
    ~myDailyTimerInterface(){}

    virtual void TimerCallback(int nTimerID) = 0;
};
class myDailyTimer :
    public myThread
{
public:
    boost::asio::io_service m_IO;
    boost::asio::deadline_timer * m_pTimer;
    tm m_tmSpecificTime;
    std::string m_strSpecificTime;
    int m_nTimerID;
    myDailyTimerInterface* m_pParent;
public:
    myDailyTimer();
    ~myDailyTimer();

    void SetTime(tm strIN, int nID); // msec
    void TimerCallback();

    //Override
    void ThreadMain();
protected:
    std::string MakeStringSpecificTime();
    void AddOneDay();
};
myDailyTimer.cpp
myDailyTimer::myDailyTimer()
{
    m_pTimer = 0;
    m_strSpecificTime = "";
}

myDailyTimer::~myDailyTimer()
{
    EndThread();
    if (m_pTimer != 0)
    {
        m_pTimer->cancel();
        delete m_pTimer;
    }
    m_IO.stop();
    m_IO.~io_service();
    int i = 0;
    i++;
}

void myDailyTimer::SetTime(tm tmIN, int nID) // msec
{
    if (m_pTimer != 0)
    {
        m_pTimer->cancel();
        delete m_pTimer;
    }
    m_tmSpecificTime = tmIN;
    m_strSpecificTime = MakeStringSpecificTime();
    m_nTimerID = nID;
    m_pTimer = new boost::asio::deadline_timer(m_IO, boost::posix_time::time_from_string(m_strSpecificTime));
    m_pTimer->async_wait(boost::bind(&myDailyTimer::TimerCallback, this));

    myThread::Start();
}

std::string myDailyTimer::MakeStringSpecificTime()
{
    time_t localTime;
    localTime = mktime(&m_tmSpecificTime); // time is GMT local
    struct tm * ptm = gmtime(&localTime); // convert time to GMT +0
    char veccNextTime[64];
    memset(veccNextTime, 0, sizeof(veccNextTime));
    sprintf(veccNextTime, "%d-%02d-%02d %02d:%02d:%02d.000",
        ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
        ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    std::string strTemp(veccNextTime);
    return strTemp;
}

void myDailyTimer::AddOneDay()
{
    m_tmSpecificTime.tm_mday += 1;
    mktime(&m_tmSpecificTime); /* normalize result */
}

void myDailyTimer::TimerCallback()
{
    if (m_pParent != 0)
        m_pParent->TimerCallback(m_nTimerID);
    //m_timer->expires_from_now(boost::posix_time::milliseconds(m_nTimerDuration));
    AddOneDay();
    m_strSpecificTime = MakeStringSpecificTime();
    m_pTimer->expires_at(boost::posix_time::time_from_string(m_strSpecificTime));
    m_pTimer->async_wait(boost::bind(&myDailyTimer::TimerCallback, this));
}

//Override
void myDailyTimer::ThreadMain()
{
    while (!IsEndThread())
        m_IO.run();
    int j = 0;
    j++;
}

最佳答案

正如DanMašek所提到的,在这里明确地调用析构函数并不是一个好的模式。停止io_service的标准方法是停止所有待处理的“工作”,然后等待io_service::run函数返回。另外,为防止io_service::run函数过早返回,最好创建io_service::work对象的实例。

希望您能够将此示例修改为您的用例:

namespace asio = boost::asio;

class MyTimer {
    using Clock = std::chrono::steady_clock;

  public:
    MyTimer(Clock::duration duration) 
      : _work(_ios)
      , _timer(_ios)
      , _thread([this] { _ios.run(); })
    {
      _ios.post([this, duration] { start(duration); });
    }

    ~MyTimer() {
      _ios.post([this] { stop(); });
      _thread.join();
    }

  private:
    void start(Clock::duration duration) {
      _timer.expires_from_now(duration);
      _timer.async_wait([this](boost::system::error_code) {
          // NOTE: Be careful here as this is run from inside
          //       the thread.
          if (!_work) {
            // Already stopped.
            std::cout << "Stopped" << std::endl;
            return;
          }
          std::cout << "Timer fired" << std::endl;
        });
    }

    void stop() {
      _work.reset();
      _timer.cancel();
    }

  private:
    asio::io_service _ios;
    boost::optional<asio::io_service::work> _work;
    asio::steady_timer _timer;
    std::thread _thread;
};

int main() {
  auto* my_timer = new MyTimer(std::chrono::seconds(1));
  delete my_timer;
  return 0;
}

关于c++ - 如何删除boost io_service,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40065496/

相关文章:

c++ - 尝试同步队列时发生段错误

c++ - 无法使用 VS2012 链接到静态 boost 库,而动态链接工作正常

c++ - boost 序列化 : Does the default constructor have to be public?

c++ - 段错误背包问题

c++ - MailSlot写发送同样的东西三次C/C++

c++ - 尝试编译基本的 Boost 属性树示例时出现问题 - 编译错误。该怎么办?

c++ - boost::asio strand 包裹的线程不能立即工作

c++ - 链接 boost::thread

c++ - 在模板类定义下定义内联函数

c++ - 如何为 CentOS 6.10 编译 node.js(库问题)