我有一个简单的程序,它由两个线程组成:
1.由Qt QApplication::exec
操作的主GUI线程
boost::asio::io_service
操作的TCP网络线程
TCP事件,例如连接或接收数据,导致GUI发生变化,最常见的是QLabel上的setText
和隐藏各种widget,目前我正在TCP客户端线程中执行这些动作,这似乎很不安全。
如何正确地将事件发布到Qt主线程?我正在寻找boost::asio::io_service::strand::post
的Qt变体,它将事件发布到boost::asio::io_service
事件循环。
3条答案
按热度按时间jdzmm42g1#
如果不想让TCP类成为QObject,另一个选择是使用QMetaObject::invokeMethod()函数。
那么要求是你的目标类必须是一个QObject,并且你必须调用一个在目标上定义的slot。
假设您的QObject定义如下:
然后可以从TCP类调用该插槽。
如果您使用
Qt::DirectConnection
进行调用,则插槽将在TCP线程中执行,并且它可能/将会崩溃。编辑:因为
invokeMethod
函数是静态的,所以可以从任何类调用它,并且该类不需要是QObject。sy5wg1nm2#
如果你的对象是从QObject继承的,只需发送一个信号并将其连接(使用标志Qt::QueuedConnection)到主线程的一个插槽。信号和插槽是线程安全的,应该优先使用。
如果它不是QObject,那么你可以创建一个lambda函数(使用GUI代码),并使用一个单次QTimer在主线程中排队,然后在回调中执行它。
原始贷记https://riptutorial.com/qt/example/21783/using-qtimer-to-run-code-on-main-thread
但要小心,因为如果你删除对象,你的应用可能会崩溃。两种选择是:
up9lanfz3#
对@CJCombrink优秀答案的推广不需要定义插槽,您也可以使用lambda: