2016-05-15 266 views
0

我正在運行Visual Studio 2012,並試圖瞭解如何std :: async工作。我創建了一個非常簡單的C++控制檯應用程序:std :: launch :: async被阻塞,像一個同步進程

#include "stdafx.h" 
#include <future> 
#include <iostream> 

void foo() { 
    std::cout << "foo() thread sleep" << std::endl; 
    std::this_thread::sleep_for(std::chrono::seconds(5)); 
    std::cout << "foo() thread awake" << std::endl; 
} 

int main() 
{ 
    std::future<void> res = std::async(std::launch::async, foo); 
    res.get(); 
    std::cout << "MAIN THREAD" << std::endl; 

    system("pause"); 

    return 0; 
} 

我最初的期望是看到「主線程」的打印輸出出現以前「富()線程清醒」,因爲這兩個線程異步運行,同時FOO ()由於其睡眠行爲而落後。但是,這不是實際發生的情況。調用res.get()會阻塞,直到foo()喚醒,然後纔會進入「MAIN THREAD」打印輸出。這是一個同步行爲的指示,所以我想知道如果我可能錯過了一些東西,或者沒有完全掌握實現。我已經瀏覽了很多關於這個問題的帖子,但是仍然沒有任何意義。任何幫助,將不勝感激!

+1

您認爲['future :: get'](http://en.cppreference.com/w/cpp/thread/future/get)是做什麼的? –

+1

在std :: future <>實例上調用'get()'會阻塞該線程,直到得到結果。 http://en.cppreference.com/w/cpp/thread/future/get – user2296177

+0

那麼這與直接調用foo()函數有什麼不同? – boondocks

回答

6
res.get(); 

直到異步結束。不管你如何告訴它運行

http://en.cppreference.com/w/cpp/thread/future/get

,直到把它完成get不能給你結果。

+0

如何以異步方式執行我的foo()函數相對於主線程?還有另一種方法,或者我做錯了什麼? – boondocks

+2

如果你關心結果,只要延遲調用'get()'直到必須得到結果的最後一刻。如果你不關心結果,只需使用std :: thread並立即調用detach()。只是要清楚,它是異步運行 - 只是你立即停止你的主線程並迫使它等待。 – xaxxon

+0

@xax在你不能保證它們終止之前(如何? – Yakk

0

問題是res.get()必須等待其線程完成才能得到結果(如果有的話)。要查看運動中的併發性,您需要將get()移動到您想要同時運行的其他代碼之後。

這個例子可以使它更清晰一點:

#include <ctime> 
#include <cstdlib> 
#include <future> 
#include <iostream> 

void foo(int id) { 
    std::cout << "foo(" << id << ") thread sleep" << std::endl; 
    // random sleep 
    std::this_thread::sleep_for(std::chrono::seconds(std::rand() % 10)); 
    std::cout << "foo(" << id << ") thread awake" << std::endl; 
} 

int main() 
{ 
    std::srand(std::time(0)); 

    std::future<void> res1 = std::async(std::launch::async, foo, 1); 
    std::future<void> res2 = std::async(std::launch::async, foo, 2); 
    std::future<void> res3 = std::async(std::launch::async, foo, 3); 

    std::cout << "MAIN THREAD SLEEPING" << std::endl; 

    std::this_thread::sleep_for(std::chrono::seconds(20)); 

    std::cout << "MAIN THREAD AWAKE" << std::endl; 

    // now wait for all the threads to end 
    res1.get(); 
    res2.get(); 
    res3.get(); 

    system("pause"); 

    return 0; 
} 
1

那麼,這是std::future::get如何工作 - 它會阻止,直到future有一些結果或異常提供。

這並不是說async同步工作,它是異步工作,只是因爲你阻塞了等待結果的線程。

的想法是異步推出一些任務,做一些事情。同時,只叫get當你需要的結果,你可能想通了,這還不是最尺度能夠事情..

,如果你使用Visual Studio 2015,您可以訪問std::futureconcurrency::task(Microsoft PPL庫)的await關鍵字以及您自己的兼容定義類型。這實現了非阻塞行爲。

#include "stdafx.h" 
#include <future> 
#include <iostream> 

void foo() { 
    std::cout << "foo() thread sleep" << std::endl; 
    std::this_thread::sleep_for(std::chrono::seconds(5)); 
    std::cout << "foo() thread awake" << std::endl; 
} 

std::future<void> entry(){ 
    await std::async(std::launch::async, foo); 
    std::cout << "foo has finished, back in entry()\n"; 
} 

int main() 
{ 
    std::cout << "MAIN THREAD" << std::endl; 
    entry(); 
    std::cout << "BACK INMAIN THREAD" << std::endl; 
    system("pause"); 

    return 0; 
} //make sure to compile with /await flag 
相關問題