gpt4 book ai didi

Qt同步方法

转载 作者:行者123 更新时间:2023-12-02 01:39:27 27 4
gpt4 key购买 nike

我是一个纯 Qt 初学者,目前想了解它的基本概念以及如何以正确的方式使用它们。我的问题可能会以某种方式出现“蹩脚”,我想提前为此道歉。话虽如此,问题是:

我想实现一个方法,它“阻塞”直到处理完成(出于什么原因......)。为了完成内部工作,我必须使用一个异步类,当它在后台完成工作时发出一个信号。我想以阻塞方式使用它:

QEventLoop myLoop;

workerClass x;

QObject::connect(x, SIGNAL(finished()), &myLoop, SLOT(quit()));

/* x is asnchrounous and will emit "finished" when ist job is done */
x.doTheJob();

myLoop.exec();

那行得通吗?根据周围的其他一些帖子 - 它应该。但究竟发生了什么?

当刚刚创建 QEventLoop 的新实例时,是否自动意味着从 myLoop 发出的信号会在该新处理程序中自动处理?此外,循环在开始工作后开始一段时间。在 myLopp 启动之前,当它发出已经“完成”的信号时会发生什么?

一位同事告诉我,我可以使用
QEventLoop myLoop;

workerClass x;

QObject::connect(x, SIGNAL(finished()), &myLoop, SLOT(quit()));

/* doTheJob is a slot now */
QMetaObject::invokeMethod(x, "doTheJob", Qt::QueuedConnection);

myLoop.exec();

我明白,在这种情况下 doTheJob 是从事件循环中调用的。但是来自哪个事件循环? invokeMethod() 没有被告知在特定的事件循环 (myLoop) 中调用该方法,那么为什么应该将事件发布到 myLoop 而不是进入“外部”循环?事实上,当时 myLoop 甚至没有运行......

我希望我能够将我的问题传达给专家可以理解。

非常感谢,
迈克尔

最佳答案

关键是QObject::connect :

QObject::connect(x, SIGNAL(finished()), &myLoop, SLOT(quit()));

此函数表示何时 finished()发出, myLoop.quit()应该在事件发生后立即调用。所以在你的例子中,
<--------thread A-------->  |  <--------thread B-------->
QEventLoop myLoop;
workerClass x;
x.doTheJob(); starts thread B
sleep in exec() workerClass::JobA();
sleeping..... workerClass::JobB();
sleeping..... workerClass::JobC();
sleeping..... workerClass::JobD();
sleeping..... workerClass::finished();
sleeping.....
wake up by quit();
myLoop.quit必须在线程 A 休眠后调用,否则线程 A 可能会永远休眠,因为 quit可以在 sleep 前调用。您必须找到一种方法来指定这一点。但是如何?看看 QObject::connect ,最后一个参数是
Qt::ConnectionType type = Qt::AutoConnection

关于 Qt::AutoConnection ,

(Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used.



信号在线程 B 和接收器中发出 myLoop在线程 A 中,这意味着您正在使用 Qt::QueuedConnection:

The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.



插槽 myLoop.quit当控制返回到事件循环时调用, myLoop.exec .换句话说, quit仅在 exec 时调用在跑。这正是我们想要的,一切正常。因此,您的第一个示例始终正确运行,因为信号和插槽使用 Qt::QueuedConnection 连接在一起。 (来自默认值 Qt::AutoConnection )。
你的第二个例子工作正常,因为 QObject::connect也一样。

如果你把它改成 Qt::DirectConnection ,故事不一样。 quit在线程 B 中调用,可能是 quitexec 之前被调用线程 A 将永远休眠。所以在这种情况下,你永远不应该使用 Qt::DirectConnection .

故事是关于 QObject::connect和线程。 QMetaObject::invokeMethod与此无关,它只是在线程执行 exec 时调用一个函数。功能。

关于Qt同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29297854/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com