2016-11-24 90 views
5

我試圖實現定時器與標準環境 下面是一個代碼,我有:定時器掛起主線程

bool shutdownDetected = false; 

void signal_handler(const int sigid) 
{ 
    shutdownDetected = true; 
} 

int main(int argc, const char * argv[]) 
{ 
    signal(SIGTERM, (sig_t)signal_handler); 

    std::async(std::launch::async, [&]() { 
     std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
     std::cout << "On TIMER!" << std::endl; 
    }); 

    std::cout << "main function" << std::endl; 

    while (!shutdownDetected) { 
    } 

    return EXIT_SUCCESS; 
} 

至於結果,我看到在輸出5秒後:

// 5 seconds left 
On Timer 
main function 

但希望看到:

main function 
// 5 seconds left 
On Timer 

似乎我的實現掛起主線程以及。如何避免這種情況?

+1

我不是專家,但我覺得很奇怪,你不會在['std :: future'](http://en.cppreference.com/w/cpp)上調用'.get()' /線程/未來)。 [如果你這樣做,就會給出預期的結果。](http://coliru.stacked-crooked.com/a/f04caae880926851) – Borgleader

+0

甚至不需要調用'get',真的。只需要將'future'分配給某個東西,以便稍後可以調用'get' – user4581301

+0

@ user4581301呵呵,因爲臨時會被瞬間破壞並在cout發生之前掛起主線程? – Borgleader

回答

3

你的std :: async命令返回一個std :: future,然後立即銷燬它。問題在於,對未來的破壞涉及到「加入」你創建的線程,這意味着析構函數將等待直到線程自行結束,並且在主線程中的代碼執行不會提前,直到該過程完成。

簡單的答案是將您的std :: async調用的結果分配給一個變量,並可能在您的循環中調用其get()成員函數來測試終止。

auto t = std::async(std::launch::async, [&]() { 
    std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
    std::cout << "On TIMER!" << std::endl; 
}); 

std::cout << "main function" << std::endl; 

t.get(); 
3
std::async(std::launch::async, [&]() { 
     std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
     std::cout << "On TIMER!" << std::endl; 
    }); 

,除非你可以指定由std::async返回給一個變量std::future,並保持它周圍不工作。我不知道這是爲什麼,顯然是因爲我不能去查看它。文森特Savard做,並鏈接我們的文件上destructor for std::future它說:

它可能會阻止如果所有以下爲真:共享狀態是通過調用創建到std ::異步,共享狀態尚未準備就緒,這是共享狀態的最後一個參考。

由於返回的std::future沒有分配給任何東西,它會立即銷燬並且析構函數阻塞直到完成。

我將忽略信號處理程序,因爲它與問題無關。

#include <iostream> 
#include <future> 

int main() 
{ 
    auto letMeLive = std::async(std::launch::async, []() { 
     std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
     std::cout << "On TIMER!" << std::endl; 
    }); 

    std::cout << "main function" << std::endl; 

    letMeLive.wait(); // instead of the signal handler 
    return EXIT_SUCCESS; 
}