C ++ Асинхронная функция не запускается асинхронно - PullRequest
0 голосов
/ 19 сентября 2018

Я пытаюсь запустить функцию асинхронно, но она запускается синхронно.

#include <thread>
#include <future>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

std::future<int> setPromise()
{
    auto promise = std::make_shared<std::promise<int>>();
    auto future = promise->get_future();
    auto asyncFn = [&]() {
      cout << "Async started ...\n";
      for(int i=0; i<100000; i++)
        for(int j=0; j<10000; j++) {}
      promise->set_value(400);
      fprintf(stderr, "Async ended ...\n");
    };
    std::async(std::launch::async, asyncFn);
    return future;
}

int main()
{
   std::future<int> result = setPromise();
   cout << "Asynchronously launched \n";
   int ret = result.get();
   cout << ret << endl;

   return 0;
}

Скомпилировал его с помощью следующей команды

g++ -std=c++11 -pthread promise.cpp -o promise 

Я ожидаю, что лямбда-функция будет вызываться асинхронно, и пока цикл работает в асинхронном потоке, я ожидаю журналы из главной.Но я вижу, что функция никогда не запускается асинхронно и всегда лямбда завершается, и только тогда мы получаем следующие операторы в main для выполнения

Что я ожидаю

Async started ...
Asynchronously launched
Async ended ...

Что я получаю, так это

Async started ...
Async ended ...
Asynchronously launched

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

При вызове строки ниже

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

создается временный future объект, и его деструктор заканчивается только в том случае, если завершается задача, запущенная async.Таким образом, в конце области действия setPromise ее выполнение блокируется до тех пор, пока не завершится задание - asyncFn.

Вы можете прочитать о поведении будущего destrcutor здесь и что происходит, когда общее состояниебудущее не готово.

0 голосов
/ 19 сентября 2018

Вероятно, он работает асинхронно, просто быстро завершается.

Чтобы убедиться в этом, вам нужно освободить условие гонки регистрации.

Примерно так (только идея):

std::future<int> setPromise()
{
    std::atomic_flag canGo = ATOMIC_FLAG_INIT;

    auto asyncFn = [&] {
        while (!canGo);
        log("Async started ..."); // also use thread-safe logging
        ...
    }

    std::async(std::launch::async, asyncFn);
    log("letting it go...");
    canGo.test_and_set();

    ...
}

Также обратите внимание, что iostream не является поточно-ориентированным, поэтому при экспериментах лучше использовать поточно-безопасный регистратор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...