2016-05-15 5 views
0

Ich verwende Visual Studio 2012 und versuche zu lernen, wie std :: async funktioniert. Ich habe eine sehr einfache C++ Konsolenanwendung erstellt:std :: launch :: async blockiert wie ein Synchronisierungsprozess

#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; 
} 

Meine anfängliche Erwartung war, „Haupt-Thread“ Ausdruck erscheint vor „foo() Thread wach“, um zu sehen, da die beiden Threads asynchron ausgeführt werden, mit dem foo() aufgrund seines Schlafverhaltens hinterherhinken. Dies ist jedoch nicht das, was tatsächlich passiert. Der Aufruf von res.get() blockiert, bis foo() aufwacht, und erst dann kommt der Ausdruck "MAIN THREAD". Dies ist bezeichnend für ein synchrones Verhalten, also frage ich mich, was passiert, wenn ich vielleicht etwas vermisse oder die Implementierung nicht vollständig verstehe. Ich habe zahlreiche Beiträge zu diesem Thema durchgesehen, kann aber immer noch keinen Sinn daraus machen. Jede Hilfe wäre willkommen!

+1

Was denkst du ['future :: get'] (http://en.cppreference.com/w/cpp/thread/future/get)? –

+1

Der Aufruf von 'get()' auf einer 'std :: future <>' Instanz blockiert den Thread, bis Sie das Ergebnis erhalten. http://en.cppreference.com/w/cpp/thread/future/get – user2296177

+0

dann wie unterscheidet sich das als Aufruf der Funktion foo() direkt? – boondocks

Antwort

6
res.get(); 

blockiert, bis der Async abgeschlossen ist.

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

Unabhängig davon, wie Sie es sagen laufen, get können Sie die Ergebnisse nicht geben, bis es fertig ist.

+0

Wie kann ich meine foo() - Funktion in asynchroner Weise in Bezug auf den Haupt-Thread ausführen? Gibt es einen anderen Ansatz, oder mache ich etwas falsch? – boondocks

+2

Wenn Sie sich für das Ergebnis interessieren, verzögern Sie einfach den Aufruf von 'get()' bis zum letzten möglichen Moment, bevor Sie das Ergebnis haben müssen. Wenn Ihnen das Ergebnis egal ist, verwenden Sie einfach std :: thread und rufen Sie sofort detach() auf. Um es klar zu sagen, es läuft asynchron - es ist nur so, dass Sie sofort Ihren Haupt-Thread anhalten und ihn warten lassen. – xaxxon

+0

@xax detaching threads, wenn Sie nicht garantieren können, dass sie (wie?) Vor dem Ende von main beenden, ist nicht ratsam. – Yakk

0

Das Problem ist, dass res.get() warten muss, bis der Thread beendet ist, bevor er sein Ergebnis erhält (falls vorhanden). Um die Parallelität in Bewegung zu sehen, müssen Sie die get() nach dem anderen Code verschieben, den Sie gleichzeitig ausführen möchten.

Dieses Beispiel kann es ein wenig klarer:

#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

Nun, das ist, wie std::future::get Werke - es blockiert, bis future eine Folge oder eine Ausnahme zu bieten hat.

das bedeutet nicht, dass async synchron arbeitet, ist es ist asynchron arbeiten, es ist nur, weil Sie den Thread blockieren, die auf das Ergebnis wartet.

die Idee war es, eine bestimmte Aufgabe asynchron zu starten, tun mittlerweile etwas und get nur anrufen, wenn Sie das Ergebnis benötigen, wie Sie herausgefunden könnte, es nicht die schuppen Lage Sache ist ..

, wenn Sie Mit Visual Studio 2015 können Sie auf das Schlüsselwort sowohl für std::future und concurrency::task (Microsoft PPL-Bibliothek) als auch für Ihre eigenen kompatiblen definierten Typen zugreifen. Dies erreicht nicht blockierendes Verhalten.

#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 
Verwandte Themen