【问题标题】:Use member function in std::packaged_task with std::thread (not std::async)将 std::packaged_task 中的成员函数与 std::thread 一起使用(不是 std::async)
【发布时间】:2014-10-24 16:44:20
【问题描述】:

我正在尝试从 std::thread 获取 std::future,似乎唯一的方法(?)这样做是使用 std::packaged_task。嗯,另外,我想在std::thread中调用的函数是一个类成员函数。我可以找到这个线程Use member function in std::packaged_task,但他们使用 std::async 而不是 std::thread。我试图根据该帖子进行编译,但是当我尝试在此处编译此代码时:

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

class test
{
    int fthread(int b)
    {
        return a + b;
    }

    int a;
public:
    test(int a_) : a(a_) {}

    int run(int b)
    {
        std::packaged_task<int(int)>
            task(std::bind(&test::fthread, this));

        //std::thread a(std::move(std::ref(task)), 5, 1);
        std::thread th(std::move(std::ref(task)), b);//<--Edit typo...

        std::future<int> fut = task.get_future();

        return fut.get();
    }
};

int main()
{
    int a = 5, b = 1;
    test t(a);

    int c = t.run(b);

    if (c != (a+b))
        return 1;
    return 0;
}

我在 MSVC 2013 上收到以下错误:

error C2064: term does not evaluate to a function taking 1 arguments
class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments

1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(1137) : see reference to function template instantiation 'int std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >::_Do_call<_Ty,0x00>(std::tuple<_Ty &>,std::_Arg_idx<0x00>)' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(1137) : see reference to function template instantiation 'int std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >::_Do_call<_Ty,0x00>(std::tuple<_Ty &>,std::_Arg_idx<0x00>)' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\xrefwrap(283) : see reference to function template instantiation 'int std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >::operator ()<_Ty>(_Ty &&)' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\xrefwrap(283) : see reference to function template instantiation 'int std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >::operator ()<_Ty>(_Ty &&)' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >,false>::_ApplyX<_Rx,_Ty>(_Ty &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Rx=int
1>  ,            _Ty=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >,false>::_ApplyX<_Rx,_Ty>(_Ty &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Rx=int
1>  ,            _Ty=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(226) : while compiling class template member function 'int std::_Func_impl<_MyWrapper,_Alloc,_Ret,int>::_Do_call(int &&)'
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<int,int>>
1>  ,            _Ret=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,int>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<int,int>>
1>  ,            _Ret=int
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,int>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Alloc=std::allocator<std::_Func_class<int,int>>
1>  ,            _Fty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,int>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Alloc=std::allocator<std::_Func_class<int,int>>
1>  ,            _Fty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,int>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,int>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Alloc=std::allocator<std::_Func_class<int,int>>
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,int>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,int>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Alloc=std::allocator<std::_Func_class<int,int>>
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,int>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,int>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\future(588) : see reference to function template instantiation 'std::function<_Ret (int)>::function<_Ty>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fx=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\future(588) : see reference to function template instantiation 'std::function<_Ret (int)>::function<_Ty>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fx=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\future(1742) : see reference to function template instantiation 'std::_Packaged_state<_Ret (int)>::_Packaged_state<_Ty>(_Fty2 &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fty2=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          C:\MesProgs\Microsoft Visual Studio 12.0\VC\include\future(1744) : see reference to function template instantiation 'std::_Packaged_state<_Ret (int)>::_Packaged_state<_Ty>(_Fty2 &&)' being compiled
1>          with
1>          [
1>              _Ret=int
1>  ,            _Ty=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>  ,            _Fty2=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          main.cpp(51) : see reference to function template instantiation 'std::packaged_task<int (int)>::packaged_task<std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >>(_Fty2 &&)' being compiled
1>          with
1>          [
1>              _Fty2=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]
1>          main.cpp(51) : see reference to function template instantiation 'std::packaged_task<int (int)>::packaged_task<std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >>(_Fty2 &&)' being compiled
1>          with
1>          [
1>              _Fty2=std::_Bind<true,int,std::_Pmf_wrap<int (__cdecl test::* )(int),int,test,int>,test *const >
1>          ]

如果有任何帮助,我将不胜感激!谢谢

【问题讨论】:

  • 您可能还想查看std::promise 作为使用futures 的一种方式。
  • 谢谢,我去看看。

标签: multithreading c++11 stl packaged-task


【解决方案1】:

你有几个问题:

  • 您没有为 bind 中的预期参数指定占位符。应该是std::bind(&amp;test::fthread, this, std::placeholders::_1),或者更好的是[this](int i){ return fthread(i); }

  • 您正在尝试将reference_wrapper 移动到std::thread,而您应该直接移动packaged_taskstd::thread a(std::move(task), ... 或通过值传递reference_wrapperstd::thread a(std::ref(task), ....。如果将packaged_task 移动到线程中,请务必在移动前提取其future

  • packaged_task 只接受一个参数时,您将两个参数 - 5 和 1 - 传递给 std::thread 构造函数。通过检查main 中的测试,您希望该参数为bstd::thread a(std::move(task), b);

  • 您不加入或分离线程,因此其析构函数将调用std::terminate

解决所有这些结果:

int run(int b)
{
    std::packaged_task<int(int)>
            task(std::bind(&test::fthread, this, std::placeholders::_1));
    std::future<int> fut = task.get_future();

    std::thread(std::move(task), b).join();

    return fut.get();
}

在语义上等同于:

int run(int b)
{
    return std::async(std::launch::async, [this,b]{ return fthread(b); }).get();
}

Demo at Coliru

【讨论】:

  • 天哪,谢谢!关键是占位符,我对此一无所知!这两个参数是一个错字(我更改了代码并忘记在此处更新,抱歉),对于我所读到的内容,连接是不必要的,因为我使用的是能够阻塞当前线程的 future::get()直到工作完成。再一次感谢你!干杯,老挝
  • 实际上,我在没有 thread::join() 的情况下调用 future::get() 是错误的,它崩溃了。顺便说一句,在创建线程之前必须调用get_future(),否则它也会崩溃。
猜你喜欢
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多