std::async from std::async in windows xp



此示例在 Windows7 和 ideone.com 上打印所有 2 条消息,但在 Windows XP 上无法打印第二条消息。我做错了什么?如果是错误,我应该在哪里报告?

使用 Visual Studio 2017 为 Windows XP 编译,平台工具集v141_xp。

#include <iostream>
#include <future>
#include <thread>
using namespace std;
int main()
{
auto f1 = async(launch::async, []()->int {
cout << "in outer async" << endl;
auto f2 = async(launch::async, []()->int {
cout << "in inner async" << endl;
return 2;
});
f2.get();
return 1;
});
f1.get();
return 0;
}

使用标准::线程而不是标准::异步作为内部函数时的UPD - 它在两个系统上都运行良好

auto f2 = thread([]()->int {
cout << "in inner async" << endl;
return 2;
});
f2.join();

UPD2

Visual Studio 2017 CL.exe版本 19.14.26428 工具集v141_xp

命令行:

/permissive- /Yu"stdafx.h" /GS /GL /analyze- /Wall /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"Releasevc141.pdb" /Zc:inline /fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_USING_V110_SDK71_" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /std:c++17 /FC /Fa"Release" /EHsc /nologo /Fo"Release" /Fp"Releasetestasync.pch" /diagnostics:classic 

UPD3看起来像launch::async在Windows XP上使用时被忽略

vector<future<void>> v;
for( int i = 0; i < 10; i++ )
v.push_back(async(launch::async, []() {cout << "thread" << endl; this_thread::sleep_for(5s); }));
for( auto &f : v )
f.get();

在Windows7 上,这需要 ~6 秒才能完成,在 Windows XP 上需要 ~50 秒

在 Windows 上,std::async(...)位于线程池之上。所以可能会出现僵局。在f1中,您可以运行新任务并调用f2.get(),这会阻止f2直到完成。但是,如果auto f2 = async(...)选择了运行f1的同一线程,那么您就会死锁,并且您的程序不应该完成。如果是这样,那么情况并非如此。

更新

请在此处阅读有关Microsoftstd::async实现的信息。 它说:

C++标准指出,如果策略是 launch::async,则该函数会创建一个新线程。但是,Microsoft实施目前不符合要求。它从 Windows 线程池获取其线程,在某些情况下,该线程池可能会提供回收的线程而不是新线程。这意味着 launch::async 策略实际上是作为 launch::async|launch::d eferred 实现的

还有另一个答案,它揭示了Microsoftstd::async实现的一个特殊功能:

  • 限制它使用的后台线程总数,之后对 std::async 的调用将阻塞,直到线程变为空闲。在我的机器上,这个数字是 768。

因此,我假设,如果 ThreadPool 中只有一个线程,那么从任务内部调用std::async将死锁。考虑到您的UPD3,可能是您的情况。

我真的建议阅读提到的答案,这样您就可以理解为什么Microsoft的std::async不同以及如何正确使用它。

最新更新