4

不同的Qt 方法调用和信号槽连接类型有以下选择:

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

但是,我需要像 "Blocking Auto Connection" 这样的东西,如果目标对象位于同一个线程中,它将充当直接连接,否则会阻塞队列连接。

如何?


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

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

1 回答 1

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.

一般警告:必须注意线程间调用,与标准相同Qt::BlockingQueuedConnection。例如,如果目标方法对调用线程(事件循环阻塞)执行相同类型的方法调用(或信号),那么两个线程都会死锁

于 2013-11-12T10:11:23.870 回答