在std :: packaged_task中使用成员函数 [英] Use member function in std::packaged_task

查看:312
本文介绍了在std :: packaged_task中使用成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的应该是很容易,但我不能得到它...



我想做的是启动一个成员函数在某些时间点在后台
中的类。该功能的结果也应该是外部可用的。所以我想在构造函数中准备任务(设置未来的变量,...)并在稍后启动它。



我试图结合std :: (packed_task | async | future)但我没有得到它工作。



这段代码不能编译,但我想它显示我想做什么: / p>

  class foo {
private:
//此函数将作为线程在后台运行
//当它被触发在某个点开始
bool do_something(){return true; }

std :: packaged_task< bool()>任务;
std :: future< bool>结果;

public:
foo():
任务(do_something),//是的,这是错的,但是怎么做呢?
result(task.get_future())
{
//做一些初始化的东西
.....
}
〜foo(){ }

void start(){
//启动任务为asynchron线程
std :: async as(std :: launch :: async,task); //也不工作...
}

//这个函数应该返回do_something的结果
bool get_result(){return result.get(); }
};

提前感谢!

方案

只需使用 std :: bind()

  #include< functional& // for std :: bind()

foo():
task(std :: bind(& foo :: do_something,this)),
// ^
result(task.get_future())
{
// ...
}

这里的东西:

  std :: async as(std :: launch :: async,task)
// ^ ^
//试图声明一个变量?因为你想要的是调用 std :: async()



$ b
函数,而不是声明一个(不存在)类型 std :: async()的对象。作为第一步,将其改为:

  std :: async(std :: launch :: async,task)

但是,请注意,这不足以让任务异步运行:因为奇怪的行为在返回的未来被丢弃时, std :: async(),您的任务将总是被执行,如同您同步启动它 - 析构函数返回的未来对象将阻塞,直到操作完成。 (*)



为了解决这个最后一个问题,你可以在你的 result 比分配结果 std :: packaged_task :: get_future()返回的未来构造时):

  result = std :: async(std :: launch :: async,task); 
// ^^^^^^^^

(*)I 认为MSVC忽略此规范并实际上异步地执行任务。因此,如果您使用VS2012,您可能不会遇到此问题。



编辑:



正如Praetorian在他的回答中所提到的,上面的问题仍然是有问题的,因为 packaged_task 将在 async()的实现中的某个时间尝试。要解决这个问题,您可以使用任务对象包装在引用包装器中/ functional / refrel =nofollow> std :: ref()


What I want to do should be quite easy, but I don't get it...

All I want to do is to start a member function of a class in background at some certain point in time. The result of that function should also be "externally" available. So I want to prepare the task in the constructor (setting the future variable, ... ) and start it at some later point.

I tried to combine std::(packaged_task|async|future) but I didn't get it to work.

This snippet will not compile, but I think it shows what I want to do:

class foo {
private:
  // This function shall run in background as a thread
  // when it gets triggered to start at some certain point
  bool do_something() { return true; }

  std::packaged_task<bool()> task;
  std::future<bool> result;

public:
  foo() : 
    task(do_something), // yes, that's wrong, but how to do it right?
    result(task.get_future()) 
  {
    // do some initialization stuff
    .....
  }
  ~foo() {}

  void start() {
    // Start Task as asynchron thread
    std::async as(std::launch::async, task); // Also doesn't work...
  }

  // This function should return the result of do_something
  bool get_result() { return result.get(); }
};

Thanks in advance!

解决方案

Just use std::bind():

#include <functional> // For std::bind()

foo() :
    task(std::bind(&foo::do_something, this)),
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    result(task.get_future()) 
{
    //  ...
}

Moreover, you are doing the wrong thing here:

std::async as(std::launch::async, task)
//         ^^
//         Trying to declare a variable?

Since what you want is to call the std::async() function, not to declare an object of a (non-existing) type std::async(). So as a first step, change this into:

std::async(std::launch::async, task)

Notice, however, that this will not be enough to get the task running asynchronously: because of the odd behavior of std::async() when the returned future is discarded, your task will always be executed as if you started it synchronously - the destructor of the returned future object will block until the completion of the operation. (*)

To solve this last problem, you can hold the returned future in your result member variable (rather than assigning to result the future returned by std::packaged_task::get_future() upon construction):

    result = std::async(std::launch::async, task);
//  ^^^^^^^^

(*) I think that MSVC ignores this specification and actually executes the task asynchronously. So if you are working with VS2012, you may not suffer from this problem.

EDIT:

As correctly mentioned by Praetorian in his answer, the above would still be problematic, since a copy of the packaged_task would be attempted at some point within the implementation of async(). To work around this problem, you wrap your task object in a reference wrapper by using std::ref().

这篇关于在std :: packaged_task中使用成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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