的std ::异步指定启动时不执行::异步 [英] std::async not executing when specifying launch::async

查看:118
本文介绍了的std ::异步指定启动时不执行::异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许我错过了新的的std ::异步的C ++ 11的正确用法,但这种说法(在以上的 CP preference.com ):


  

如果异步标志设置(即政策和放大器;!的std ::推出::异步= 0),仿佛的std ::螺纹(F,ARGS催生然后异步执行上执行一个单独的线程函数f ...),但如果函数f返回一个值或抛出一个异常,它被存储在通过的std ::将来访问的共享状态异步返回给调用者。


让我觉得,我的线程应该用这句话立即启动:

 的std ::异步(的std ::推出::异步,MyFunctionObject());

而不必等待调用的std ::未来::得到()。这似乎不是这样(用MSVC 13编译)。如果这不是被这句话本身引发的,应该如何得到这个如果我不关心的std ::未来对象的返回值触发?

例如:

 的#include<螺纹>
#包括LT&;&iostream的GT;
#包括LT&;阵列GT;
#包括LT&;&未来GT;静态的std ::互斥write_mutex;类Cpp11Threads {
上市:
    //为函数对象函数operator
    void运算符()(){
        const int的NUM_THREADS = 50;        //静态数组性病
        的std ::阵列<的std ::螺纹*,NUM_THREADS> WORKER_THREADS;        //一系列基于
        对于(的std ::螺纹*&放大器;螺纹:WORKER_THREADS){            // LAMBDA前pression
            线程=新的std ::线程(
                [] {
                    静态INT I = 0;
                    write_mutex.lock();
                    性病::法院LT&;< 你好,我是幸福的标准线#<<我++ LT;<的std :: ENDL;
                    write_mutex.unlock();
                });
        }        对于(的std ::螺纹*&放大器;螺纹:WORKER_THREADS){
            线程>加入();
            删除线程;            // nullptr而非NULL
            线程= nullptr;
        }
    }
};诠释主(){
    的std ::异步(的std ::推出::异步,Cpp11Threads());
    返回0;
}


解决方案

你必须知道的第一件事情是MSVC 的std ::异步做的不是的符合C ++ 11的标准。

根据C ++ 11标准,的std ::异步的std ::未来返回值块直到的std ::异步完成。

MSVC的实现没有。这使得他们的的std ::异步貌似更友好的使用,但在实践中它是相当棘手的。

不过,由于的std ::异步的行为在的std ::线程来描述,我们可以看看会发生什么,当你揭开序幕的std ::线程,未能把它清理干净。由此产生的的std ::线程被有效分离。一旦你退出,C ++标准没有的未指定的会发生什么这样的的std ::线程 S,留给了特定的实现。

根据了一些快速研究,当一个MSVC Windows程序熄灭的主要结束时,线程终止。

总之,你的程序需要你以某种方式推出的线程或另一个重新同步,使他们能够完成他们的任务,prevent主程序从退出。一个简单的方法做到这一点是存储返回的std ::未来异步任务,的前退出。

如果你有一个符合C ++编译器11,你尝试异步将不能是异步的,因为它会立即冻结在匿名的破坏的std ::未来它返回。

最后,需要注意的是开展线程 S等不得安排创建后立即运行。如何以及何时运行不predictable。

在C ++ 11并发原语仅仅是原语。他们中许多人有古怪的行为,像这样一个事实:的std ::线程通话终止如果它没有被破坏分离 ED或加入 ED和异步的倾向阻止,如果你不保存未来。它们可用于简单的任务,或用于写入更高级别的库,但它们不是用户友好的。

Maybe I'm missing the correct usage of the new std::async in C++11, however this statement (over at cppreference.com):

If the async flag is set (i.e. policy & std::launch::async != 0), then async executes the function f on a separate thread of execution as if spawned by std::thread(f, args...), except that if the function f returns a value or throws an exception, it is stored in the shared state accessible through the std::future that async returns to the caller.

Makes me think that my thread should start immediately with this statement:

std::async(std::launch::async, MyFunctionObject());

Without having to wait for calling the std::future::get(). This seems to not be the case (compiling with MSVC 13). If this is not triggered by this statement itself, how should this get triggered if I don't care about the return value of the std::future object?

Example:

#include <thread>
#include <iostream>
#include <array>
#include <future>

static std::mutex write_mutex;

class Cpp11Threads {
public:
    // Function operator for Function-Object
    void operator()() {
        const int num_threads = 50;

        // Static std array
        std::array<std::thread*, num_threads> worker_threads;

        // Range based
        for (std::thread*& thread : worker_threads) {

            // Lambda expression
            thread = new std::thread(
                [] {
                    static int i = 0;
                    write_mutex.lock();
                    std::cout << "Hello, I am happy Std thread #" << i++ << std::endl;
                    write_mutex.unlock();
                });
        }

        for (std::thread*& thread : worker_threads) {
            thread->join();
            delete thread;

            // nullptr instead of NULL
            thread = nullptr;
        }
    }
};

int main() {
    std::async(std::launch::async, Cpp11Threads());
    return 0;
}

解决方案

The first thing you have to know is that MSVC std::async does not conform to the C++11 standard.

Under the C++11 standard, std::async's std::future return value blocks until the std::async completes.

MSVC's implementation does not. This makes their std::async seemingly more friendly to use, but in practice it is quite tricky.

However, as std::async's behavior is described in terms of std::thread, we can look at what happens when you kick off a std::thread and fail to clean it up. The resulting std::thread is effectively detached. Once you exit main, the C++ standard does not specify what happens to such std::threads, leaving it up to your particular implementation.

Based off some quick research, when a MSVC windows program goes off the end of main, the threads are terminated.

In short, your program needs to resynchronize with the threads you launched in some way or another, so that they can complete their tasks, and prevent the main program from exiting main. An easy way to do that is to store the returned std::future from your async task, and wait on it before main exits.

If you had a conforming C++11 compiler, your attempted async would fail to be asynchronous, as it would block immediately upon the destruction of the anonymous std::future it returned.

Finally, note that launched threads and the like may not be scheduled to run immediately after creation. How and when they run is not predictable.

The C++11 concurrency primitives are merely primitives. Many of them have quirky behavior, like the fact that a std::thread calls terminate if it is destroyed without being detached or joined, and async's tendency to block if you don't store the future. They can be used for simple tasks, or for writing higher level libraries, but they are not user friendly.

这篇关于的std ::异步指定启动时不执行::异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆