QSharedPointer在emit中被销毁

问题描述 投票:1回答:1

我在Qt上是一个新奇的问题,QSharedPointer在信号中传递了一些问题。我正在使用两个线程(UI和一个worker)。工作人员使用包含自定义QObject的QSharedPointer的信号向UI发送信号:

class MyObject : QObject {...}

class Window : public QWidget {
    Q_OBJECT
public slots:
    void onFound(QSharedPointer<MyObject>);
}

class Worker : public QObject {
    Q_OBJECT
public signals:
    void found(QSharedPointer<MyObject>);
}

我使用found将工作者onFound与windows Qt::QueuedConnection连接起来,因为它们存在于不同的线程中,因此通信必须是异步的。

现在我观察到以下行为,当我传递最后一个引用我的对象的qazxsw poi时:

  • 信号moc将引用转换为我指向QSharedPointer的指针并激活它。
  • 函数返回导致共享指针和要销毁的相应对象。

这不是我的预期 - 虽然这是合理的。 QSharedPointer一般是通过这种方式传递信号吗?如果是这样的话,在排队的时候是否有一种机制来保持参考?

我考虑了下面的解决方案,但我对它们都没有完全没问题:

  1. 在某个地方保留一个引用,以便在排队时保持引用。但是在哪里这是一个合理的地方,我应该什么时候放手。
  2. 建立连接void*然后我仍然必须以某种方式切换线程(与以前相同的情况)
  3. 引入一个带有Qt::DirectConnection参数的新信号/槽,用于传递要在目标线程中执行的lambda函数并捕获我的共享指针的副本。 (这是我目前的解决方案,但它不是优雅的,不是吗?)

您还有其他建议或想法吗?

c++ qt qt5 qt-signals qsharedpointer
1个回答
1
投票

信号返回不会破坏相应的对象。 std::function调用复制共享指针。这是QMetaObject::activate信号的实现:

send

您可能正在经历一场竞赛:当发出信号的线程恢复执行时,目标线程已经收到了该对象。因此,它在发射线程中显示对象消失了 - 因为到那时,它就是。然而,目标对象接收实例就好了。它工作正常。

下面的示例说明它适用于单线程和多线程情况,然后通过确保目标线程始终赢得竞争来重现您的问题:

// SIGNAL 0
void IO::send(const QSharedPointer<Unique> & _t1)
{
    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
© www.soinside.com 2019 - 2024. All rights reserved.