首页 > 解决方案 > Windows XP 中来自 std::async 的 std::async

问题描述

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

使用 Visual Studio 2017 平台工具集 v141_xp 为 windows 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;
}

使用 std::thread 而不是 std::async 作为内部函数时的 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"Release\vc141.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"Release\testasync.pch" /diagnostics:classic 

在 windows xp 上使用时,UPD3 看起来像 launch::async 被忽略

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 秒

标签: c++visual-c++windows-xp

解决方案


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

更新

请阅读std::async 此处的 Microsoft 实施。它说:

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

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

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

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

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


推荐阅读