C++ 11 std::async 使用问题

使用std::async遇到的异常问题

1.crash 在std中 thread 和 condition_variable相关的地方

2.导致线程卡住

vs2013下使用没问题,升级到vs2015后出现

 


#include "stdafx.h"

#include 

#include 

#include 

#include 

#include 

using namespace std;

void connect()

{

	std::async(std::launch::async, [](){

		for (int i = 0; i < 5; ++i)

		{

		Sleep(1000);

			cout << i << endl;

		}

	});

	cout<< "finished connection" << endl;

}

int _tmain(int argc, _TCHAR* argv[])

{

	connect();

	while (1){

		cout << "main thread" << endl;

		Sleep(500);

	}

	cout << "end connection" << endl;

	return 0;

}

这样的写法在vs2013中没有问题,但在 vs2015中就引发以上两个问题,甚至间接的引发别的异常

在vs2015编译器下,包括在gcc编译器下,该异步方法会阻塞调用它的线程,直到子线程结束。而在vs2013的编译器下,异步方法不会阻塞当前线程.

std::future::~future
 
C++
 
Thread support library
 
std::future
 
~future();

(since C++11) 



Releases any shared state. This means 
if the return object or provider holds the last reference to its shared state, the shared state is destroyed; and 
the return object or provider gives up its reference to its shared state; and 
these actions will not block for the shared state to become ready, except that it may block if all of the following are true: the shared state was created by a call to std::async, the shared state is not yet ready, and this was the last reference to the shared state. 

终于在官方文档中http://en.cppreference.com/w/cpp/thread/future/~future找到了解释,原文如上:

 

具体原因就是:

当以下三个条件全部满足时,future的析构有可能会阻塞线程状态变为ready,也就是可能会阻塞线程:
1.共享状态是通过std::async创建
2.共享状态还不是ready状态
3.被析构的future对象是共享状态的最后一个引用

最后其实还是vs2013对C++11标准不完全支持

问题:

I updated my Visual Studio from 2013 to 2017. Compiling was fine but it seems like that the std::async call didn't open a new thread. (I cant see a new one in the thread-window while debugging. Also it looks like the thread which calls the the async function does the job...)

That is my function call:

std::async(std::launch::async, myfunction, this); 

I didn't change anything in my code and in VS2013 was everything working fine.

Any Idea? Google can't tell me a lot about this but maybe i have the wrong keywords. So keywords would also help!

Thank you

回答1:

You need to hold on to the std::future returned by async otherwise the destructor of the temporary will block until the work is finished.

auto t = std::async(std::launch::async, myfunction, this);

 

回答2:

In VS2013, std::async does not obey the C++ standard.

There was a disagreement, and the developers working on MSVC wanted std::async's std::future to behave like every other std::future.

The standard disagreed.

They released a non-standard compliant std::future in 2013. In 2015 if I remember correctly, they started following the standard.

The standard states that the destructor of the std::future owning the shared state generated by std::async( std::launch::async blocks until the task is complete.

This is because, in practice, dangling threads are bad for programs behaving in a predictable manner.

You are now in charge of owning and persisting the future returned from

auto f = std::async(std::launch::async, myfunction, this); 

and f.wait or f.geting it when you need it to be ready.

This may require changing how your code works; for example, keeping a vector of futures around (if you have more than one), or adding a std::future member to this and storing it (this also ensures that the async call doesn't outlive the object lifetime!).


As a second note, std::async on windows also uses a bounded thread pool; if there are more than a certain number of async tasks active, new tasks may not be launched.

They have plans to fix it (as it goes against the advice in the standard), but at this point I would still recommend using std::thread, and if you need std::async like behavior implementing something similar yourself.

My personal tendency is to create problem-specific thread_pools that own a certain number of std::threads, but let you queue tasks and get futures (with custom extensions that give me very limited continuation capabilities) back from it.

This makes the thread ownership and dependencies more explicit, and avoids dealing with the MSVC non-standard compliant quirks that still exist.

 

回答3:

Looks like std::async is whaiting for return to end. So, if you symply call it, doesn't work asynchronous.

std::async(std::launch::async, myfunction, this);

The Key is define an answer: myfunction must to return std::future and you need to define and same type to response.

std::future foo = std::async(std::launch::async, myfunction, this);

In case you call std::async inside a constructor, foo must be member of the class.

class MyClass {
    //Your code
    private:
        std::future exitThread;
}

And, when you call std::async must be

exitThread = std::async(std::launch::async, myfunction, this);

 

回答4:

Very simple Solution:

std::thread t(myfunction, this);
t.detach();

 

 

From VS2013 to VS2017 std::async does not start a new thread

Reference:

std::async在gcc和vc不同编译器下的不同表现(可能会阻塞)

c++11 std::async使用注意

你可能感兴趣的:(C/C++)