2016-10-16 33 views
0

我的簡化問題
我讀this thread,我試圖刪除io_service對象。我這樣做如何刪除升壓io_service對象

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

m_IO是boost::asio::io_service的一個對象。我發現我的線程被m_IO.~io_service();封鎖瞭如何刪除io_service

我的完整問題
我正在通過使用boost io_service和截止時間定時器來製作每日定時器。問題是當我想刪除我的日常計時器時,當它嘗試刪除提升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;,我的timer線程不能達到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++; 
} 


+2

'm_IO〜io_service對象();' - 這是一個代碼味道,如果我見過一個,尤其是英寸這個背景。你提到的問題特別提到的是,用戶對有問題的代碼無法控制,所以他們不得不求助於這種把戲(你沒有正確執行反正你沒有重新創建對象)。如果你需要更好地控制它的生命週期,這個問題還包含一個合理的建議,即動態分配'io_service'。然而這在這裏並不相關,因爲問題在於其餘的代碼,而不是刪除'io_service'。 –

+0

THX您的回覆,如果我想實現每天定時用'deadline_timer'的幫助下,我該怎麼辦? – sflee

+1

我在作品的答案,但請給我一些時間來把它在一起。 –

回答

1

正如丹馬塞克提到的,顯式調用析構函數是不是在這裏的良好格局。停止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; 
} 
+0

非常感謝,我試過後會將它標記爲答案。 – sflee