我正在重构一个程序,以减少对Windows特定结构的依赖。线程模型是“传统的”Windows GUI模型:有一个'主'GUI线程只执行非常短的操作,以保持GUI响应;所有较长的任务都在“工人”线程中完成。所有工作线程只与gui线程通信,并且它们通过:: SendMessage和:: PostMessage(SendMessage阻塞,PostMessage不是,对于那些不熟悉Windows API的人)进行通信。 '通知'样式消息,'嘿我已经完成处理',或者所有参数都可以适合2个32位值(Send / PostMessage的参数)的消息与PostMessage一起发送,因为没有数据访问需要同步;必须使用SendMessage传递大量数据的消息,然后gui线程(快速)复制它在“真正”处理之前所需的一切(或将“真正的”处理传递给另一个工作线程)。这样,永远不会同时访问相同的数据。它有一些限制,但到目前为止它对我们有用;主要的优点是它是一个如此简单的模型,你几乎从不必考虑可能发生的事情或进行显式同步,因为从来没有共享的数据访问权。
我想解除的“唯一”限制是这个模型仅用于单向通信:它是从工作者到gui线程。到目前为止,它已经为我们的目的工作了,但我想转移到一个所有线程都相等的模型,任何线程都可以将消息“发布”到任何其他线程,双向;然后在此基础上,我想构建一些东西来检查'工作线程'只与'主线程'通信,反之亦然;从来没有'工人线程'彼此之间。通过这种方式,我们将来可以灵活地在线程确实需要通信n:n的其他用例中重用该机制。
所以现在我的问题是:如何使用c ++ 11或boost线程库复制此行为?理想情况下,我会有一个全局函数或一个单例的成员,可以从任何线程调用,第一个参数是某种线程的id'调入',也许某种'消息id'(消息必须首先注册,很像win32中的RegisterUserMessage())和特定于消息的void *。接收者将负责投射和解释消息。然后以某种方式在“接收”线程的上下文中调用消息处理方法。
所以我想的可能是其他类派生的基类'ThreadBase'; 'ThreadBase'将提供纯虚函数'HandleMessage(unsigned int msg_id,void * data)'左右。也许这个'ThreadBase'本身派生自std :: thread?或者有一个std :: thread成员?然后在(对于这个例子)main()我做:
ThreadManager::RegisterMessage(1234); // 'Thread1 is done'
Thread1 t1(1); // Thread1 and Thread2 both derived from 'ThreadBase'
Thread2 t2(2); // Construction of t1 and t2 would immediately start the thread; alternatively they could have a Run() member?
然后从t1的任何地方我都能做到:
MyData data;
ThreadManager::SendMessage(2, 1234, (void*)&data);
这会调用带有参数'1234'和'& data'的Thread2 :: HandleMessage()。
我希望我在这里有意义 - 我想从我的问题的措辞中可以清楚地看出,我对win32 API之外的多线程并不十分熟悉。这个想法是否有意义?我忽略了缺点?如何使用线程原语实现这一点?感谢。
答案 0 :(得分:0)
嗯。你的问题显然不符合SO问题格式;),但我不会理解你。
我将尝试解释一下C ++中的线程模型。最值得记住的是它实际上是在Posix线程上建模的。所以你可以在那里找到Posix的东西,但不能找到特定于Windows的东西。特别是,它意味着它缺乏对消息传递的任何内置支持。您可以拥有的关闭是一个条件变量,但您只能等待单个条件变量,并且不能复用。要使用消息传递,您需要实现自己的消息队列,或使用第三方库(boost肯定有一个,以及一堆其他库)。