从另一个线程发出信号是否安全?
Is it safe to emit signal from another thread?
从另一个线程在对象上发出信号是否安全(如果插槽连接为QueuedConnection
(?我找不到会提到这一点的特定文档,我找到的最相关的引用是这样的:
QObject 是可重入的。它的大多数非GUI子类,如QTimer, QTcpSocket,QUdpSocket和QProcess也是可重入的,使其成为 可以同时从多个线程使用这些类。 请注意,这些类旨在从中创建和使用 在单个线程内;在一个线程中创建一个对象并调用 它从另一个线程的功能不能保证工作。
这表明它可能不行,这也适用于信号吗?QMetaObject::activate
里面有一个QMutexLocker
,所以在我看来它可能是线程安全的......?
#include <QCoreApplication>
#include <QTimer>
#include <thread>
#include <iostream>
struct Foo : public QObject
{
Q_OBJECT
public:
Foo(QObject* parent) : QObject(parent) {}
public slots:
void run()
{
connect(this, &Foo::signal, this, [] { std::cout << "activated"; }, Qt::QueuedConnection);
std::thread t([this] { emit signal(); });
if (t.joinable()) t.join();
}
signals:
void signal() const;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Foo* b = new Foo(&a);
QTimer::singleShot(0, b, &Foo::run);
return a.exec();
}
Qt基于事件队列。每个Qt线程都有自己的队列和相关的事件循环。因此,当您遇到 2 个不同对象存在 2 个不同线程并且一个通过信号/插槽机制(通过自动或排队连接(连接到另一个线程的情况时,在发射过程中会发生以下情况:信号中的代码创建一个事件并将其发布到对象接收器的队列中。接收方的事件循环正在队列中运行,找到发布的事件并执行适当的槽。
队列保证是线程安全的,因此跨线程发出信号是绝对安全的。您问题中的引用谈到了您直接调用生活在T1
中的物体的情况T2
.
有一篇关于线程、qobjects、信号、插槽以及一切如何相互关联的好文章:线程事件 QObjects。如果您想更深入地了解它,我建议您阅读它。
关于有问题的代码。您有一个排队的连接,这意味着发送方和接收方是存在于一个线程中还是不同的线程中并不重要。发送方和接收方是 2 个对象还是相同对象并不重要。所述例程将相同。如果您创建了自动连接,则它将具有直接呼叫,但您没有。以及文档中的相关引用:
另一方面,您可以安全地从您的 QThread::run(( 实现,因为信号发射是线程安全的。
是的,这是首选方法,因为qt GUI可以防止直接从另一个线程更改线程 所以你应该从线程发出一个信号,并在线程拖曳中连接(接收它(,并根据信号类型执行一些线程代码 如果您尝试直接执行代码,则会收到此错误
QObject::setParent:无法设置父级,新的父级位于不同的线程中
- 通过网络、跨平台传递std::变体是否安全
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 在函数结束后使用指向变量的指针是否安全?
- 逐字节删除 void* 是否安全?
- 在 RAII 构造中修改 RVO 值是否安全?
- 线程调用的函数对对象删除是否安全?
- 将对象的字节复制到数组并再次复制回来是否安全
- 使用枚举为数组编制索引是否安全?
- 返回从字符串文本创建的静态string_view是否安全?
- 在cstlib中将#include_next替换为#include是否安全
- 由并发无序映射查找线程调用的函数是否安全?
- 使用 c++ 原子时编写"y=++x"是否安全?
- 从另一个线程发出信号是否安全?
- 从其存储的回调中删除 std::函数是否安全
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 当我在C++中调用 struce 的只读静态成员时,线程是否安全
- 同时调用 ASIO 对象的 API 是否安全?
- 使用自己的迭代器分配容器是否安全?