使用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 byasync
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
'sstd::future
to behave like every otherstd::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 bystd::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 fromauto f = std::async(std::launch::async, myfunction, this);
and
f.wait
orf.get
ing 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 tothis
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 ofasync
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 needstd::async
like behavior implementing something similar yourself.My personal tendency is to create problem-specific
thread_pool
s that own a certain number ofstd::thread
s, but let you queue tasks and getfuture
s (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使用注意