如何将信号连接到boost :: asio :: io_service在其他线程上发布工作时

How to connect signal to boost::asio::io_service when posting work on different thread?

本文关键字:线程 其他 布工作 工作 service 连接 信号 boost io asio      更新时间:2023-10-16

我正在尝试使用Boost :: Lockfree队列来管理任务。这些任务检索数据,并将在工作线程上处理。数据检索后,应将信号发送到带有数据的主线程。在应用程序开始时,将工人线程产生,只是继续轮询队列。我是Boost :: Asio的新手,但是从我的研究来看,它似乎是线程之间发送信号的最佳机制。

我已经看过几个示例,特别是:

  • 当boost :: asio :: io_service run方法块/unblocks
  • 感到困惑
  • boost asio帖子不起作用,io_service :: post后立即退出

这是我的代码:

#include "stdafx.h"
#include <thread>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/optional.hpp>
#include <boost/thread.hpp>
#include <boost/signals2.hpp>
typedef boost::signals2::signal<void(int)> signal_type;
class Task
{
public:
    Task(int handle) : _handle(handle) {};
   ~Task() {};
   virtual void Execute()
   {
      int result = _handle * 2;
   }
private:
   int _handle;
};

class Manager
{
public:
   Manager() 
   {
      _mainService = std::make_shared<boost::asio::io_service>();
      _workerService = std::make_shared<boost::asio::io_service>();
      _work = std::make_shared<boost::asio::io_service::work>(*_workerService);
      _threadStarted = false;
      Start();
   };
   ~Manager() {};
   void WorkerMain()
   {
      _workerService->poll();
   }
   void Start()
   {
      if (_threadStarted) return;
      _workerThread = std::thread(&Manager::WorkerMain, this);
      _threadStarted = true;
   }
   void Stop()
   {
      if (_threadStarted == false) return;
      _mainService->stop();
      _workerThread.join();
      _mainService.reset();
   }
   void OnSignalFetchCompleted(int value)
   {
      int asdf = 0; //do stuff with data on main thread
   }
   void ProcessData(signal_type& signal)
   {
      int i = 0;
      do
      {
         _queue.consume_one([&](std::shared_ptr<Task> task)
         {
            task->Execute();
            //get data from task; send out signal with data
         });
         i++;
      } while (i < 3);
   }
   void QueueData(int handle)
   {
      _signalFetchCompleted.connect(boost::bind(&Manager::OnSignalFetchCompleted, this, _1));
      _workerService->post(boost::bind(&Manager::ProcessData, boost::ref(_signalFetchCompleted))); //!!does not compile
      std::shared_ptr<Task> task = std::make_shared<Task>(handle);
      _queue.push(task);
   }
private:
   boost::lockfree::spsc_queue<std::shared_ptr<Task>, boost::lockfree::capacity<1024>> _queue;
   std::thread _workerThread;
   bool _threadStarted;
   std::shared_ptr<boost::asio::io_service> _mainService;
   std::shared_ptr<boost::asio::io_service> _workerService;
   std::shared_ptr<boost::asio::io_service::work> _work;
   signal_type _signalFetchCompleted;
};

int _tmain(int argc, _TCHAR* argv[])
{
   std::shared_ptr<Manager> mgr = std::make_shared<Manager>();
   mgr->QueueData(5);
   mgr->QueueData(10);
   mgr->Stop();
   return 0;
}

我在我无法解决的_workerService->帖子行上遇到了一个编译错误:

1>C:Boostboost/bind/mem_fn.hpp(333): error C2784: 'T *boost::get_pointer(const boost::scoped_ptr<T> &)' : could not deduce template argument for 'const boost::scoped_ptr<T> &' from 'const signal_type'
1>          C:Boostboost/smart_ptr/scoped_ptr.hpp(150) : see declaration of 'boost::get_pointer'
1>          C:Boostboost/bind/mem_fn.hpp(352) : see reference to function template instantiation 'R (__cdecl &boost::_mfi::dm<R,Manager>::call<const U>(U &,const void *) const)' being compiled
1>          with
1>          [
1>              R=void (signal_type &)
1>  ,            U=signal_type
1>          ]
1>          C:Boostboost/bind/mem_fn.hpp(352) : see reference to function template instantiation 'R (__cdecl &boost::_mfi::dm<R,Manager>::call<const U>(U &,const void *) const)' being compiled
1>          with
1>          [
1>              R=void (signal_type &)
1>  ,            U=signal_type
1>          ]
1>          C:Boostboost/bind/bind.hpp(243) : see reference to function template instantiation 'R (__cdecl &boost::_mfi::dm<R,Manager>::operator ()<T>(const U &) const)' being compiled
1>          with
1>          [
1>              R=void (signal_type &)
1>  ,            T=signal_type
1>  ,            U=signal_type
1>          ]

任何帮助解决此方法错误或对此方法的一般评论的任何帮助将不胜感激。谢谢。

鉴于新信息,问题是您的boost::bind。您正在尝试调用成员函数而没有对象来调用它:您正在尝试调用ProcessData,但是您尚未告诉绑定要调用哪个对象的绑定。您需要给它一个Manager才能致电:

_workerService->post(boost::bind(&Manager::ProcessData, this, boost::ref(_signalFetchCompleted)));

这将在this上调用ProcessData,并传递给_signalFetchCompleted

编译器错误似乎是在谈论您构建boost::asio::io_service::work对象,并且您传递了它不正确的参数:

error C2664: 'boost::asio::io_service::work::work(const boost::asio::io_service::work &)' : cannot convert argument 1 from 'std::shared_ptr<boost::asio::io_service>' to 'boost::asio::io_service &'

boost::asio::io_service::work具有一个构造函数,该构造函数采用boost::asio::io_service&和一个复制构造函数;但是,您将其传递给std::shared_ptr<boost::asio::io_service>

_work = std::make_shared<boost::asio::io_service::work>(_workerService);

在这里,_workerServicestd::shared_ptr<boost::asio::io_service>,但是您需要boost::asio::io_service&。尝试以下内容:

_work = std::make_shared<boost::asio::io_service::work>(*_workerService);

我认为BOOST :: ASIO不是您任务的最佳解决方案。您是否了解到有条件变量?它们更简单,可以用来实现您的目标。