Std::Async Won't Spawn a New Thread When Return Value Is Not Stored

std::async won't spawn a new thread when return value is not stored

From just::thread documentation:

If policy is std::launch::async then runs INVOKE(fff,xyz...) on its own thread. The returned std::future will become ready when this thread is complete, and will hold either the return value or exception thrown by the function invocation. The destructor of the last future object associated with the asynchronous state of the returned std::future shall block until the future is ready.

In

std::async(std::launch::async, foo, arg1, arg2);

The returned future is not assigned anywhere and its destructor blocks until foo finishes.

C++ std::async does not spawn a new thread

Change to this:

auto _ = std::async(std::launch::async, [](){ 
while(true) cout << "async thread" <<endl;
});

Document:

If the std::future obtained from std::async is not moved from or bound
to a reference, the destructor of the std::future will block at the
end of the full expression until the asynchronous operation completes,
essentially making code such as the following synchronous:

std::async(std::launch::async, []{ f(); }); // temporary's dtor waits
for f() std::async(std::launch::async, []{ g(); }); // does not start
until f() completes

How to use std::async with void method with no parameters?

AsyncTestClass::AsyncMethod1, being a non-static member function, can only be called if an instance of AsyncTestClass is supplied. You probably meant this:

std::async(&AsyncTestClass::AsyncMethod1, this)

This creates a std::future object whose value will be obtained by evaluating this->AsyncMethod1().

By the way, the return value of std::async should be assigned to a variable, otherwise the call will block. See std::async won't spawn a new thread when return value is not stored. If you have C++20, the compiler will catch this for you thanks to [[nodiscard]].

std::async is blocking/pausing the parent thread

std::async returns a future which wait on destruction, you have to use a member for it or use std::thread directly (detached).

std::async is not called immediately

The call to async returns as soon as the new thread is created. You now have two separate threads, and the only correlation between the operations in those two threads is that the thread created by the call to async must have finished before the call to f.get() returns. So the behavior you're seeing is consistent with the requirements. The behavior you expect is also consistent with the requirements. That's the point of running separate threads: they run independently until you do something to synchronize them.

What's the C++ 11 way to fire off an asynchronous task and forget about it?

Just detach it immediately after creation.

std::thread([](){ run_async_task(); }).detach();

Once detached, the thread will no longer be joinable, so ~thread() will have no effect.
This answer discusses more details of this behavior.

As mentioned by W.B. below, std::async will not work for the following reason, pulled from this reference.

If the std::future obtained from std::async has temporary object
lifetime (not moved or bound to a variable), the destructor of the
std::future will block at the end of the full expression until the
asynchronous operation completes

scope block when use std::async in function other than the main function

This QUESTION answered in :

main thread waits for std::async to complete

Can I use std::async without waiting for the future limitation?

Whoever, If you store the std::future object, its lifetime will be extended to the end of main and you get the behavior you want.

void printData() 
{
for (size_t i = 0; i < 5; i++)
{
std::cout << "Test Function" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}

std::future<void> runningAsync()
{
return std::async(std::launch::async, test);
}

int main()
{
auto a = runningAsync();

std::cout << "Main Function" << std::endl;
}

That's a problem because std::future's destructor may block and wait for the thread to finish. see this link for more details

When to use std::async vs std::threads?

It's not really an either-or thing - you can use futures (together with promises) with manually created std::threads. Using std::async is a convenient way to fire off a thread for some asynchronous computation and marshal the result back via a future but std::async is rather limited in the current standard. It will become more useful if the suggested extensions to incorporate some of the ideas from Microsoft's PPL are accepted.

Currently, std::async is probably best suited to handling either very long running computations or long running IO for fairly simple programs. It doesn't guarantee low overhead though (and in fact the way it is specified makes it difficult to implement with a thread pool behind the scenes), so it's not well suited for finer grained workloads. For that you either need to roll your own thread pools using std::thread or use something like Microsoft's PPL or Intel's TBB.

You can also use std::thread for 'traditional' POSIX thread style code written in a more modern and portable way.

Bartosz Milewski discusses some of the limitations of the way std::async is currently specified in his article Async Tasks in C++11: Not Quite There Yet

Different behaviour in std::async between Visual Studio 2013 and 2015

MSVC had a bug in 2013. The std::async's returned std::future's destructor must block; they deliberately did not have it block because they where arguing for a different standard in committee.

They fixed this before MSVC 2015.

A way to get back most of the old behavior is to write a thread pool class, and submit jobs to it; have it spawn threads whenever all of its threads are working and a new job is submitted. At destruction, the thread pool class cleans up the threads it owns. Then use it's job submission mechanism instead of std::async.

In any case, avoid using std::async on MSVC, as it contains still another standards-defying (if not breaking) feature of using a thread pool limited by some hardware-dependent constant; if you have too many active std::async's, new ones won't start. This is in violation of the advice and spirit given by the C++ standard, but not technically in violation (as the C++ standard gives ridiculous leeway to not-threading thread implementations). It can easily lead to hard to track down bugs that only happen when your application scales up and uses std::async in more spots.

Maybe this was fixed in some iteration of MSVC, but last report I read was that it was still in 2015.

This is another reason to write your own thread pool job queue. At least you'll have control over semantics, instead of getting whatever random broken or half-broken implementation MSVC is currently shipping.



Related Topics



Leave a reply



Submit