Почему мой поток вызывает функциональный объект, а не присваивает его возвращаемое значение будущему объекту моего packaged_task?

Я хочу узнать, как получить возвращаемое значение функции с помощью packaged_task.

В приведенном ниже коде я создаю поток, который выполняет мою функцию DoTask. Затем я связываю эту функцию с packaged_task и заставляю ее ждать, пока я связываю ее с myTask packaged_task. Я извлекаю будущий объект myTask. Теперь я разблокирую условную переменную в DoTask (notify_one), чтобы он завершился. Я делаю get() для будущего myTask, чтобы получить значение возвращаемого bool в DoTask.

Но вместо того, чтобы ждать возврата DoTask, DoTask вводит код, который выполняет "INVOKE a function object", и get() никогда не выполняется.

Что удерживает DoTask от установки будущего, которого я ожидал, и вместо этого вызывает функциональный объект?

#include "stdafx.h"
#include <future>
#include <memory>
#include <thread>
#include <condition_variable>
#include <mutex>

std::condition_variable notifyCondVar;
std::mutex mu;

bool DoTask() 
{
  {
    std::unique_lock< std::mutex > locker( mu );
    notifyCondVar.wait( locker );
  }
  return true;
}

int main()
{
  std::thread packageTaskThread( DoTask );
  std::packaged_task< bool() > myTask( std::bind( DoTask ) );
  std::future< bool > taskFuture = myTask.get_future();
  notifyCondVar.notify_one();
  bool okay = taskFuture.get();
  packageTaskThread.join();

  return 0;
}

1 ответ

Решение

У вас есть поток работает DoTask и packaged_task дал указание запустить DoTask, Вы никогда не выполняли задачу, поэтому следующие две вещи неверны:

  1. Поток никогда не прекратится;
  2. Будущее задачи никогда не будет удовлетворено.

Возможно, вы хотели вместо этого переместить-построить поток из упакованной задачи:

#include <future>
#include <memory>
#include <thread>
#include <condition_variable>
#include <mutex>

std::condition_variable notifyCondVar;
std::mutex mu;

bool DoTask() 
{
  std::unique_lock<std::mutex> locker(mu);
  notifyCondVar.wait(locker);

  return true;
}

int main()
{
  std::packaged_task<bool()> myTask([]() { return DoTask(); });
  std::future<bool> taskFuture = myTask.get_future();

  std::thread packageTaskThread(std::move(myTask));

  notifyCondVar.notify_one();
  bool okay = taskFuture.get();

  packageTaskThread.join();
}

Вы можете увидеть примеры использования для std::packaged_task в этой документации.

(Кстати ваш дополнительный блок области в DoTask полностью излишним.)

Другие вопросы по тегам