我设法在工作器C ++ std::thread
中实现了基于GUI Qt的应用程序,如here所述。现在,我需要主线程和辅助线程进行通信。
我的问题是:如何从主线程向工作线程传递消息(浮点数数组),以便更新GUI?
我有一个执行实时信号处理的应用程序。我的目标是创建一个Qt GUI,可以将其插入到我的应用程序中,以可视化各种信号,而不会影响实时性。我研究了如何完成此操作的不同方法,并得出结论,此post非常详细地描述了我需要的内容并提供了解决方案。但是,没有有关主线程和工作线程如何相互通信的信息。
我尝试使用here中描述的Futures / Promises方法来完成线程间通信。尽管我可以使该示例运行,但无法将其集成到我的项目中。原因是这种方法依赖于工作线程内部有一个繁忙的循环,该循环不断检查主线程是否已发送新消息。但是,在Qt应用程序中,程序一旦进入a.exec()
中的主事件循环,便会阻塞。这样可以防止繁忙的循环检查,从而导致程序死锁。
这就是我生成GUI工作线程的方式(基于this发布)。
#include <thread>
// Start the Qt realtime plot demo in a worker thread
int argc = 0;
char **argv = NULL;
std::thread t1
(
[&] {
QApplication application(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return application.exec();
}
);
答案 0 :(得分:1)
您可以使用Qt自己的方法在线程之间进行通信。每个Qt对象都有一个线程亲和力。如果在单独的GUI线程中创建MainWindow
对象,则该对象将附加到该线程。如果您使用Qt信号和插槽并将其与Qt::QueuedConnection
连接,则无论该信号来自何处,都会通过该线程的主循环在对象的线程中调用该插槽。
请注意,您可以在MainWindow
类中定义信号,但是由于它们是公共的,因此可以从外部调用它们。这意味着您不需要单独的发送对象。例如,在MainWindow
构造函数中,您可以将其自身的信号连接到slot或lambda方法。
要发出MainWindow
信号,可以在GUI线程外将MainWindow
指针设置为nullptr,然后将该指针(通过lambda捕获)设置为在内部创建的新对象GUI线程。在线程外,只要您想发出信号,就可以做某事。像if (mainWindow) mainWindow->signal(…)
。我认为您仍然需要检查,因为您的GUI是可选的。
两个注意事项:
QMetaObject::invokeMethod
放弃信号,它删除了样板,但是可以通过引用在编译时检查的class方法来连接信号; QMetaObject方法在运行时使用字符串匹配。同样,在公共信号但插槽受保护的情况下,您可以确保外部代码不会意外地直接调用方法。connect(this, &MainWindow::signal, this, [this] {…});
将在接收线程中执行lambda,而connect(this, &MainWindow::signal, [this] {…});
将不。答案 1 :(得分:0)
对于信号处理,您通常不需要qts虚拟调用的开销。除此之外,
在git@github.com:midjji / convenient_multithreaded_qt_gui.git
中找到了用于gui通讯线程的好解决方案。然后仅是
enter code here
run_in_gui_thread(new RunEventImpl([](){
QMainWindow* window=new QMainWindow();
window->show();
}));
随时可以在任何线程中调用,同时还要在bg中为您进行设置。