简体   繁体   中英

std::launch::async is blocking like a sync process

I am running Visual Studio 2012 and attempting to learn how std::async works. I have created a very simple C++ console application:

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

My initial expectation was to see "MAIN THREAD" printout appearing before "foo() thread awake" since the two threads are running asynchronously, with the foo() trailing behind due to its sleeping behavior. However, that is not what is actually happening. The call to res.get() blocks until foo() wakes up, and only then does it get to the "MAIN THREAD" printout. This is indicative of a synchronous behavior, so I am wondering what if perhaps I am either missing something, or not fully grasping the implementation. I have looked through numerous posts on this matter, but still cannot make any sense of it. Any help would be appreciated!

 res.get();

blocks until the async is done.

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

Regardless of how you tell it to run, get can't give you the results until it's done.

Well, this is how std::future::get works - it blocks until future has some result or exception to provide.

that doesn't mean that async works synchronously, it is working asynchronously, it's only because you block the thread which waits on the result.

the idea was to to launch some task asynchronously, do something meanwhile and only call get when you need the result, as you might figured out, it is not the most scale-able thing..

if you use Visual Studio 2015, you can access the await keyword both for std::future and concurrency::task (Microsoft PPL library) , and for your own compatible defined types. this achieves non-blocking behavior.

#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

The problem is that res.get() has to wait for its thread to finish before getting its result (if any). To see the concurrency in motion you need to move the get() to after the other code that you want to run at the same time.

This example may make it a little clearer:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM