这是一个关于通用c ++事件驱动的应用程序设计的问题 让我们假设我们有两个线程,一个是“Dispatcher”(或“Engine”......)和一个“Listener”(或“Client”......)。 我们假设我编写了Dispatcher代码,并将其作为库发布。当然,我也写了Listener界面 Dispatcher执行时(在Listener注册后)
listenerInstance.onSomeEvent();
事件处理代码实际上将由Dispatcher线程执行,因此如果实现Listener的人写了类似
的内容
void Listener::onSomeEvent() { while(true) ; }
调度员将永远陷入困境。
是否有一个“普通的旧c ++”(我的意思是没有boost或libsigc ++)方法来“解耦”这两个类,所以我可以确定我的Dispatcher能够正常工作,无论听众在回调中做什么?
再见,并提前致谢,答案 0 :(得分:4)
如果事件在同一个线程中被调用(我似乎理解可能是一个要求),那么你可以做的事情并不多。
如果这是在带有消息泵的Win32应用程序下,您可以注册一个Windows消息并使用表示此事件的数据调用PostMessage
,您可以修补消息循环以解释该消息并调用该事件。你获得的是各种各样的解耦,事件调用是异步的(即事件调用无论如何都会返回)。但是稍后当你处理你的消息并实际调用事件时,你的主线程仍然会被停顿,除非事件处理程序准备就绪,否则其他任何东西都不会运行。
另一种选择是为您的调用创建一个新线程(或使用线程池)。这不适用于需要某个线程的事件(即ui更新线程)。此外,这会增加同步开销和线程产生开销,您可能会破坏线程和/或CPU时间系统。
但实际上,我不认为图书馆设计师的工作是预测和避免这些问题。如果最终用户想要创建一个长事件处理程序,让他自己生成一个新的线程。如果他没有,只是想让他的特定线程处理一个事件,那就让他吧。它简化了您的工作,不会增加任何不需要的开销。
答案 1 :(得分:3)
我担心没有原生的C ++方法可以做到这一点。对于Windows,您可以使用asynchronous procedure calls (APC)
答案 2 :(得分:2)
一种方法是将onSomeEvent调用为专用线程。这不是100%防弹,但它可以避免while(true);
问题。
我希望它有所帮助
答案 3 :(得分:1)
有一种pure C++
方法可以实现你所提到的。但是,它非常无效。这是一个示例:
class Listener
{
bool myHasEvent;
private:
void ProcessEvent()
{
while (true)
{
if (!myHasEvent)
continue; //spin lock
// Do real processing
myHasEvent = false;
}
}
public:
void onSomeEvent() { myHasEvent = true; }
};
但是,我建议不要采用这种方法。相反,我会将其转换为更具特定于平台的代码。我将使用特定于操作系统的等待例程(即Win32上的if (!myHasEvent) continue;
)替换WaitForSingleObject
自旋锁,并传递事件句柄。然后,在onSomeEvent
中,我将事件设置为信号状态(即Win32上的myHasEvent = true;
),而不是SetEvent
。这样会更有效,因为线程在等待期间不会占用处理器时间。
另一种方法是盲目建议的PostMessage
。