跨线程的sigslot信号
sigslot signals across threads
我使用sigslot库来触发函数中的信号。此函数使用QtConcurrent::run在线程中运行,信号在主线程中连接。除了信号连接不是每次都能工作(比如说大约25%的故障(之外,它的工作效果与预期的一样好。
这种不稳定的行为是有问题的,我找不到解决方案。sigslot库中的信号根据多线程上下文有不同的选项,但它们都不能解决问题。
在尝试boost之前,我真的很想找到一个保持使用sigslot的解决方案,因为它是一个非常简单的库,我只需要在这部分代码中基本使用信号和插槽。我不想使用Qt,因为我更喜欢让代码的同一部分没有Qt。
任何提示都将不胜感激。
更新:由于某种原因,使用sigslot::single_thread作为绝望的尝试似乎会带来更好的结果。
signal1<int, single_threaded> Sig1;
我并不是说它解决了问题,因为它对我来说没有意义。正如文档中所解释的:单线程在单线程模式下,库不会尝试保护其内部数据结构跨线程。因此,至关重要的是,所有对构造函数、析构函数和信号的调用必须存在于单个线程中
更新2:
这是MWE。但结果是随机的。有时它完全有效,有时不是全部。我知道这听起来很奇怪,但这就是问题所在。我也尝试了boost::signals2而不是sigslot,但结果完全相同。在boost::signals2::mutex::lock((中有一个可执行的错误访问
class A {
public :
A() {}
~A() {}
sigslot::signal1<int, sigslot::multi_threaded_local> sigslot_signal;
boost::signals2::signal<void (int)> boost_signal;
void func_sigslot() {
for (int i=0;i<4;i++) {
sigslot_signal.emit_signal(i);
}
}
void func_boost() {
for (int i=0;i<4;i++) {
boost_signal(i);
}
}
};
class B : public sigslot::has_slots<sigslot::multi_threaded_local> {
public :
B() {}
~B() {}
void test(int i) {
std::cout << "signal triggered, i=" << i << std::endl;
}
};
void main() {
A a;
B b;
a.sigslot_signal.connect_slot(&b, &B::test);
a.boost_signal.connect(boost::bind(&B::test, &b, _1));
QtConcurrent::run(&a, &A::func_sigslot);//->crashes when signal emitted
QtConcurrent::run(&a, &A::func_boost);//->crashes when signal emitted
boost::thread t1(boost::bind(&A::func, &a));
t1.join();//works fine
}
Sarah Thompson的sigslot库(如果您使用的是它的话(很旧,不受支持,而且看起来很bug。没有任何类型的测试工具。原始源代码不是在现代编译器下编译的。由于MSVC以前将模板视为令牌列表,因此隐藏了一些拼写错误:显然,部分代码从未使用过!
我强烈建议您只需使用Qt或其他信号槽库
遗憾的是,您的方法不起作用:sigslot库不知道Qt的线程上下文,也不与Qt的事件循环集成。插槽是从错误的线程上下文调用的。由于您可能没有编写线程安全的插槽,因此它们不会做正确的事情,而且似乎不起作用。
sigslot库的线程支持只保护库自己的数据,而不是您的数据。设置多线程策略只会影响库的数据。这与Qt形成了鲜明对比,在Qt中,每个QObject
的线程上下文都是已知的,并使信号槽系统能够安全地工作。
为了让它发挥作用,您需要在您正在调用其插槽的所有QObject
中公开一个线程安全接口。这可以简单到:
class Class : public QObject {
Q_OBJECT
public:
Class() {
// This could be automated via QMetaObject and connect overload
// taking QMetaMethod
connect(this, &Class::t_slot, this, &Class::slot);
}
Q_SIGNAL void t_slot();
Q_SLOT slot() { ... }
}
不连接到slot()
,而是连接到t_slot()
,其中t_
前缀代表线程安全/tunk。
- Qt VTK交互风格的信号到小部件
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 线程之间的布尔停止信号
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 有可能在信号处理程序中设置promise吗
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- 在条件变量中触发错误信号的频率是多少
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 调试和自由执行中的信号处理
- 升压信号2将插槽传递到成员功能以断开连接
- C++函数包装器来捕获某些信号
- 如何在qt中将信号和插槽与另一个对象连接 --解决了
- 中止信号来自 C++ 中的中止(3) (SIGABRT)
- Qt将信号与另一个类方法连接
- C++ 信号和插槽不工作:插槽不响应事件
- Coursera :自动评分器的未知信号 11
- 跨线程的sigslot信号