我发现threadpool似乎还没有提升,但我现在可以使用它(除非有更好的解决方案)。
我有几百万个小任务要同时执行,我想使用threadpool
来安排执行任务。 threadpool
的{{3}}提供(大致)此示例:
#include "threadpool.hpp"
using namespace boost::threadpool;
// A short task
void task()
{
// do some work
}
void execute_with_threadpool(int poolSize, int numTasks)
{
// Create a thread pool.
pool tp(poolSize);
for(int i = 0; i++; i < numTasks)
{
// Add some tasks to the pool.
tp.schedule(&task);
}
// Leave this function and wait until all tasks are finished.
}
但是,该示例仅允许我安排非成员函数(或任务)。有没有办法可以安排成员函数执行?
好吧,据说是documentation,但我无法弄清楚我应该继承的Runnable
类。
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj);
我想我发现了我需要做的事情:我必须创建一个runnable,它将获取任何必要的参数(包括对具有将被调用的函数的对象的引用),然后我使用静态调度函数,用于调度给定threadpool
上的可运行:
class Runnable
{
private:
MyClass* _target;
Data* _data;
public:
Runnable(MyClass* target, Data* data)
{
_target = target;
_data = data;
}
~Runnable(){}
void run()
{
_target->doWork(_data);
}
};
以下是我在MyClass
中安排的方式:
void MyClass::doWork(Data* data)
{
// do the work
}
void MyClass::produce()
{
boost::threadpool::schedule(myThreadPool, boost::shared_ptr<Runnable>(new Runnable(myTarget, new Data())));
}
但是,library allows you to schedule a Runnable
for execution中有一个错误:
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
{
return pool->schedule(bind(&Runnable::run, obj));
}
请注意,它需要引用Pool
,但它会尝试将其称为Pool
的指针,因此我也必须修复它(只需更改{{1}转到->
)。
答案 0 :(得分:3)
要安排任何功能或成员功能 - 请使用Boost.Bind或Boost.Lambda(按此顺序)。您也可以根据自己的情况考虑使用特殊库。我可以推荐Inter Threading Building Blocks,或者如果你使用VC2010,我可以推荐Microsoft Parallel Patterns Library。
编辑:
我从来没有使用过这个库,也没有听过任何关于它的坏消息,但是它已经足够老了,仍然没有包含在Boost中。我会检查原因。
编辑2:
另一种选择 - Boost.Asio。它主要是一个网络库,但它有一个可以使用的调度程序。我会用this multithreading approach。而不是使用异步网络操作而是按boost::asio::io_service::post()
计划任务。
答案 1 :(得分:2)
我想我发现了我需要做的事情:我必须创建一个runnable,它将获取任何必要的参数(包括对具有将被调用的函数的对象的引用),然后我使用静态调度函数,用于调度给定threadpool
上的可运行:
class Runnable
{
private:
MyClass* _target;
Data* _data;
public:
Runnable(MyClass* target, Data* data)
{
_target = target;
_data = data;
}
~Runnable(){}
void run()
{
_target->doWork(_data);
}
};
以下是我在MyClass
中安排的方式:
void MyClass::doWork(Data* data)
{
// do the work
}
void MyClass::produce()
{
boost::threadpool::schedule(myThreadPool, boost::shared_ptr<Runnable>(new Runnable(myTarget, new Data())));
}
但是,库中的适配器中有一个错误:
template<typename Pool, typename Runnable>
bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
{
return pool->schedule(bind(&Runnable::run, obj));
}
请注意,它需要引用Pool
,但它会尝试将其称为Pool
的指针,因此我也必须修复它(只需更改{{1}转到->
)。
然而,事实证明,我不能使用那个提升线程池,因为我正在混合本机C ++(dll),C ++ / CLI(dll)和.NET代码:我有一个C ++ / CLI库包装本机C ++库,它使用boost :: thread。不幸的是,这会在运行时产生.
(which has previously been discussed by other people):
问题是静态提升线程库试图挂钩 本机win32 PE TLS回调以确保线程本地 boost线程使用的数据被正确清理。这不是 与C ++ / CLI可执行文件兼容。
答案 2 :(得分:0)
此解决方案是我能够使用以下信息实现的:http://think-async.com/Asio/Recipes。我尝试实现这个配方,发现代码在Windows中有效但在Linux中没有。我无法弄清楚问题,但搜索互联网时发现了一个键,它使工作对象成为代码块中的自动指针。我已经为我的示例包含了用户想要的void task()我能够创建一个便利函数并将指针传递给我的函数来完成工作。对于我的情况,我创建了一个使用函数的线程池:boost :: thread :: hardware_concurrency()来获取可能的线程数。我已经使用了下面的配方,包含15个线程的多达80个任务。
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/scoped_ptr.hpp>
// A short task
void task()
{
// do some work
}
void execute_with_threadpool( int numTasks,
int poolSize = boost::thread::hardware_concurrency() )
{
boost::asio::io_service io_service;
boost::thread_group threads;
{
boost::scoped_ptr< boost::asio::io_service::work > work( new boost::asio::io_service::work(io_service) );
for(int t = 0; t < poolSize; t++)
{
threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
}
for( size_t t = 0; t < numTasks; t++ )
{
++_number_of_jobs;
io_service.post(boost::bind(task) );
}
}
threads.join_all();
}
答案 3 :(得分:0)
想出来,你必须定义run()方法,这是最简单的方法:
class Command
{
public:
Command() {}
~Command() {}
void run() {}
};
在main()中,tp是你的线程池:
shared_ptr<Command> pc(new Command());
tp.schedule(bind(&Command::run, pc));
完成。