2

我没有想到排队信号仍然在接收线程之后传递的问题disconnect(),而是:

考虑一个Sender对象在线程 1 中生成信号并且Receiver线程 2 中有一个对象的情况,该对象具有一个通过 a 连接到Sender's 信号的插槽Qt::DirectConnection

现在,在 中Receiver::~Receiver(),我需要确保在对象已经(可能部分)被破坏时仍然没有传递任何信号。因为连接是直接的,所以插槽可以随时在线程 1 中调用,特别是可能发生在破坏Receiver' 的特定属性和破坏QObject也会断开信号的基础之间。所以,我的问题归结为:

在销毁对象之前断开线程 2 中的Sender对象是否足够,或者我是否需要确保在调用期间线程 1 中没有发出信号?ReceiverReceiverdisconnect()

我正在考虑线程 1 处于发出信号的中间的情况,例如,就在执行接收槽的顶部,并且就在那一刻,在线程 2 中,disconnect()调用完成。如果disconnect()在断开连接并阻止进一步的信号传递之前等待线程 1 完成传递信号(通过互斥体),一切都会好起来的,但我不确定情况是否如此。

4

1 回答 1

4

是的disconnect(),并且connect()正在使用互斥锁进行保护。

这些是disconnect()函数的第一行:

bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
                                    const QObject *receiver, int method_index,
                                    DisconnectType disconnectType)
{
    if (!sender)
        return false;

    QObject *s = const_cast<QObject *>(sender);

    QMutex *senderMutex = signalSlotLock(sender);
    QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
    QOrderedMutexLocker locker(senderMutex, receiverMutex);

这是connect()函数的第一行:

bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
                                 const QObject *receiver, int method_index, int type, int *types)
{
    QObject *s = const_cast<QObject *>(sender);
    QObject *r = const_cast<QObject *>(receiver);

    QOrderedMutexLocker locker(signalSlotLock(sender),
                               signalSlotLock(receiver));

如果您查看QObject文档,您可以看到:

注意:该类中的所有函数都是可重入的,但connect()、connect()、disconnect() 和 disconnect() 也是线程安全的。

编辑

当发出信号时,会调用 QMetaObject::activate 函数来锁定发送者的对象互斥锁:

void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
                           void **argv)
{
     ...
     QMutexLocker locker(signalSlotLock(sender));
于 2013-05-17T09:20:33.013 回答