在std :: packaged_task中使用成员函数 [英] Use member function in 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)
对象包装在引用包装器中/ functional / refrel =nofollow>
// ^ ^
//试图声明一个变量?因为你想要的是调用std :: async()
函数,而不是声明一个(不存在)类型
$ bstd :: 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()
的实现中的某个时间尝试。要解决这个问题,您可以使用任务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) typestd::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 toresult
the future returned bystd::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 ofasync()
. To work around this problem, you wrap yourtask
object in a reference wrapper by usingstd::ref()
.这篇关于在std :: packaged_task中使用成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!