信号和槽与Boost库中的多线程比较

5

我已经在Stackoverflow上查看了类似的问题,但仍然找不到一个好的答案:

  1. 如何实现信号和槽(signals and slots)
  2. 信号和槽是如何实现的

我对这个信号/槽机制感到困惑。

问题1:从下面的代码中可以看出,sig连接了两个函数(Hello()和World()),它们似乎是按序列化方式调用的,这也意味着一个函数(Hello())需要在进入另一个函数(World())之前完成? => 单线程程序

问题2:是否有任何方法可以启用多线程信号/槽?(=> World()将立即启动,不需要等待Hello()完成。)或者如果不建议使用,您介意告诉我原因吗?

Boost网站上的示例代码:

struct Hello 
{
  void operator()() const { std::cout << "Hello";}
};
struct World
{
  void operator()() const { std::cout << ", World!" << std::endl;}
};

boost::signal<void ()> sig;
sig.connect(Hello());
sig.connect(World());
sig();

输出: 你好,世界!

2个回答

5

问题1:
这些调用是串行化的。信号在内部所做的事情,大致上可以简化为:

foreach connection:
  call handler

因此,您不希望在处理程序中阻塞太长时间。如果需要执行大量工作,则可以从那里调用它,例如通过为其创建一个线程。
问题2:
boost signals 1甚至不是线程安全的;信号2是线程安全的,但仍然进行序列化调用。由于信号通常用于事件处理,因此通常不会在处理程序中实际执行太多的工作。
因此,在“并行”调用它们方面没有真正的好处,这些好处通常无法证明必要的线程调用开销。

3

问题1:您说得对。我已经修改了我的回答,以反映您所引用的问题

问题2:看起来您对应该线程化的内容有些困惑。在发射/捕获过程中,包含代码的是槽。因此,如果您想并发运行代码,您应该将放置在不同的线程中。

Qt支持这种行为(实际上我不知道boost是否支持),Qt手册中有一章节解释了这个问题,它建议您使用“队列处理”以实现此行为。但是,您必须在执行槽代码的线程中有“事件循环”的概念(因为您不能只是告诉工作线程“嘿,停止你的工作,改做这个!”)。

如果您不想等待,您可以直接在槽代码中生成线程。并且您应该不要忘记在两个槽都可以访问的代码中使用某种形式的“等待”函数。顺便说一下,boost和Qt都有很好的包装器来轻松处理系统线程库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接