如何实现Qt“阻止自动连接”

时间:2013-11-11 17:01:23

标签: multithreading qt

不同的Qt method invocation and signal-slot connection types有这些替代方案:

  • 直接连接:当前线程中的调用方法,明显阻塞。
  • 排队连接:从接收者的事件循环调用方法,永不阻塞。
  • 自动连接:在目标对象的线程中调用方法,阻塞当前对象,否则排队而不是阻塞。
  • 阻止排队连接:在目标对象的线程中调用方法,如果不是当前线程则阻塞,否则死锁

然而,我需要类似“阻止自动连接”的东西,如果目标对象位于同一个线程中,它将充当直接连接,否则阻塞排队连接。

如何吗


作为参考,目前的解决方案似乎归结为......这显然不是一个好方法。幸运的是,它处于一个无关紧要的位置,但仍然......无论如何,无需评论,这是代码审查问题: - )

QMetaObject::invokeMethod(target, "method", Qt::AutoConnection, ...);
// If same thread, method call is already done here and sleep is skipped
while(!target->isDone()) sleep(1);

1 个答案:

答案 0 :(得分:2)

OP未经测试的答案:

帮助方法:

Qt::ConnectionType autoBlockingConnection(const QObject *target) {
    return QThread::getCurrentThread() == target->thread()
        ? Qt::DirectConnection
        : Qt::BlockingQueuedConnection;
}

用法:

QMetaObject::invokeMethod(target, "method", autoBlockingConnection(target), ...);

这方面的潜在问题是,如果Qt尚未创建当前线程,则可能无效。

注意:不可能使用QThread :: getCurrentThreadID(),因为没有相应的非静态方法来获取target的线程ID。

常规警告:必须谨慎处理线程间调用,与标准Qt::BlockingQueuedConnection相同。例如,如果目标方法对调用线程(事件循环被阻塞)执行相同类型的方法调用(或信号) back ,则两个线程都将死锁。