从 VS2013 到 VS2017 std::async 不会启动新线程

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

本文关键字:新线程 启动 线程 VS2013 VS2017 std async      更新时间:2023-10-16

我从2013年到2017年更新了我的Visual Studio。 编译很好,但似乎 std::async 调用没有打开新线程。(调试时我在线程窗口中看不到新的。此外,看起来调用异步函数的线程可以完成这项工作......

这是我的函数调用:

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

我没有更改代码中的任何内容,在VS2013中一切正常。

知道吗?谷歌不能告诉我很多关于这个的信息,但也许我有错误的关键字。所以关键字也会有所帮助!

谢谢

在VS2013中,std::async不遵守C++标准。

存在分歧,从事MSVC的开发人员希望std::asyncstd::future像其他std::future一样运行。

标准不同意。

他们在2013年发布了一个不符合标准的std::future。 如果我没记错的话,在 2015 年,他们开始遵循该标准。

该标准指出,std::future的析构函数拥有由std::async( std::launch::async块生成的共享状态,直到任务完成。

这是因为,在实践中,悬空线程对以可预测方式运行的程序不利。

您现在负责拥有和future保留从

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

并在您需要准备就绪时f.waitf.get它。

这可能需要更改代码的工作方式;例如,保留一个期货向量(如果你有多个(,或者添加一个 std::future<?> 成员来this并存储它(这也确保异步调用不会超过对象生存期!(。


第二点说明,Windows 上的std::async也使用有界线程池;如果活动async任务的数量超过一定数量,则可能不会启动新任务。

他们有计划修复它(因为它违背了标准中的建议(,但在这一点上,我仍然建议使用 std::thread ,如果您需要std::async行为自己实现类似的东西。

我个人的倾向是创建特定于问题的thread_pool,这些拥有一定数量的std::thread,但允许您排队任务并从中获取future(使用自定义扩展,给我非常有限的延续能力(。

这使得线程所有权和依赖项更加明确,并避免处理仍然存在的 MSVC 非标准兼容怪癖。

您需要保留 async 返回的std::future,否则临时的析构函数将阻塞,直到工作完成。

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

看起来 std::async 正在等待返回结束。因此,如果您以符号方式调用它,则不会异步工作。

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

关键是定义一个答案:myfunction 必须返回 std::future,你需要定义和相同的类型来响应。

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

如果您在构造函数中调用 std::async,foo 必须是类的成员。

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

并且,当您调用 std::async 时,必须

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

非常简单的解决方案:

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