在调用boost :: thread运行一些指令后,是否有可能回到主线程?
我的代码基于proactor模式,但某个函数可能需要一些时间,所以为了不阻止整个程序,我正在创建一个运行此函数的线程。 当这个函数结束时,我需要调用另一个函数,但它必须在主线程上运行。 我有一个连接池,这不是线程安全的,我真的想避免使用互斥锁。
有没有一种稳定的方法在主线程上运行一个函数(在另一个线程上调用)?
就像在ObjectiveC performSelectorOnMaintThread
中一样答案 0 :(得分:5)
如果你想在主线程中运行一个函数,你将不得不实现某种类型的消息传递系统。例如,您将启动主线程,然后启动工作线程。工作线程将完成它的工作,而主线程将等待来自工作线程的一些返回值(即主线程将检查消息队列或那种性质的东西)。当工作线程完成时,它将向主线程的消息队列传递一个结构(即消息),该结构具有指向它希望主线程运行的函数的指针。您的消息可以非常简单:
struct message
{
typedef void (*func_ptr)(void); //or whatever your function signature would be
func_ptr function;
bool finished;
message(): function(NULL), finished(false) {}
};
因此,当工作线程完成时,它将创建一条新消息,初始化消息中的函数指针,并将该消息推回到主线程正在等待的队列中。然后主线程从队列中读取消息,并调用该函数。
BTW,并且有效地使主线程“等待”而不必将其保持在循环中并且耗尽CPU周期将是在主线程之间使用信号量或条件变量(如boost::condition
)和工人。
还有一个注意事项......“消息队列”只是一个std::queue<message>
,具有主线程读取的适当锁定访问权限,而工作线程写入。主线程还可以为工作线程写入另一个消息队列,如果需要在线程之间进行双向通信,则工作线程会读取。
答案 1 :(得分:2)
我想你可能想看看boost asio strands。它们将允许您指定哪些线程(strand)可以执行某些操作,并且它将自动在该链上排队。
请注意,一条链实际上更像是一条光纤(意思是:如果有多条链比实际线程多,则这些线将被多路复用到可用线程上)。
IIRC此不会但是你有机会明确指定主线程1。但是,这通常不是实际要求:让你轻松做的是确保链中的操作在同一个逻辑线程上运行,即不能实现并发性一条链。
琐事:提升Asio io_service.run()是消息泵的示例
以下是Boost Asio的示例页面:http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/examples.html
答案 2 :(得分:0)
在多线程应用程序中(至少对我而言)主线程没有做太多工作,并且所有内容都会偏移到启动时创建的其他线程。主线程只阻止/等待(条件变量),直到指示我们退出是好的。所有工作都在线程之间翻转/翻转,这使事情变得更加容易。
如上所述,最好的方法是使用消息队列(每个队列都包装一个工作线程或池),然后将消息发送到一个或另一个。使用回调和其他消息传递机制,您可以让“主”线程向工作线程发送消息以完成工作,并提供回调以在完成结果时将消息发回“主”线程。在此期间,“主”线程可以在等待结果时继续处理其他消息和操作,如果还有其他工作要做的话。
答案 3 :(得分:0)
如果您在Visual Studio 2010中运行,它应该始终在调试中工作。但是,由于某个错误,您可能需要禁用然后重新启用“优化”才能使发布工作。
答案 4 :(得分:0)
我有类似的情况。带有提升线程的mfc对话框。解决我添加信号2到boost线程并将它们绑定到对话框上的成员函数。当信号进入对话框成员函数时,我检查了线程ID。如果线程id与对话框线程id不同,我将boost函数推送到函数的std :: queue(相同签名)。 onidle,kickidle我检查队列并执行功能。