c++ - Qt 与正在运行的工作线程的通信

标签 c++ multithreading qt signals-slots qthread

Qt docs 为例:创建一个 Controller 和一个工作人员,将工作人员移动到特定线程并启动线程。启动/停止触发是通过信号/槽完成的。

现在假设 doWork 方法依赖于一些参数(例如中间结果的输出率(以某种可视化的形式))并且人们想通过用户界面调整该参数,同时该功能正在运行。 如果使用信号/槽机制(在接口(interface)和 worker 之间),这将不起作用,因为 worker 的接收槽将在运行的事件循环之后排队,因此将在 doWork 完成后执行.

我想出了以下解决方案:

方法一:

Worker中将参数设为public,直接通过接口(interface)修改。

class Worker : public QObject
{
    Q_Object

public:
    int parameter;
    ...
}

Interface::updateParameter(int p) { worker_instance.parameter = p; }

方法二:

将参数移动到接口(interface)本身或一些额外的类(与工作线程不同的线程中)并让工作线程在每次需要时加载它。

class Interface : public QWidget
{
    Q_Object

private:
    int parameter;

public:
    int getParameter() { return parameter; }
    ...
}

Worker::doWork() {
    ...
    interface_instance.getParameter();  // load parameter;
    ...
}

我们可以将参数放在另一个类中,并通过信号/槽机制与此类交互,而不是将参数放在接口(interface)中。

关于易用性,我绝对更喜欢方法 1。它还可以让事物保持在它们实际所属的位置。 方法 2 似乎并没有真正提供优于方法 1 的优势。 对此有何看法?

还有什么不同的方法可以处理这样的事情吗?例如观看动画,我想人们想要启用动画速度的调整,这在某种程度上需要 Hook 到动画过程中。

您对这个主题有什么想法或知识吗?

最佳答案

If one uses the signal/slot mechanism (between interface and worker) this won't work, as the receiving slot of the worker will be queued after the running event loop and thus will be executed after doWork finished.

这不是必然的,你可以让doWork()非阻塞,你做一部分工作,然后让事件循环循环,允许和其他线程通信,你可以使用排队连接以这种方式传输数据,然后执行另一个工作步骤,另一个循环等等。这使您可以监控进度、暂停、取消工作并在此期间来回传输数据。

阻塞 vs 非阻塞 worker:

main            main    
|       worker  |       worker
|------>|       |------>|
|       |       |       |
|       |       |<----->
|       |       |       |
|       |       |       |
|<------|       |<----->
|               |       |
|               |<------|
|               |   

Here我已经设置了一个示例,将工作分解为多个步骤并在不阻塞工作线程的情况下运行这些步骤以允许通信通过。概念是相同的 - 将工作拆分为工作单元,跟踪工作对象中的状态,使用带有参数的信号和槽进行控制和数据传输。

请注意不要过度使用排队连接,因为与直接连接相比它们非常慢,如果您充斥事件循环,您实际上会损失性能并且应用程序可能会挂起。考虑到目标通常是视觉或用户控制反馈,尽量不要每秒发出太多排队连接。每秒 30 次左右是响应式 UI 的最佳点,但您甚至可以做得更少。

关于c++ - Qt 与正在运行的工作线程的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34803016/

相关文章:

C++函数模板部分特化?

java - 线程和中断: Continue or exit?

java - CompletableFuture runAsync 与使用 Executor 执行每个 Runnable

c++ - 从类名转换

c++ - 如何在 QTreeWidget header 中添加按钮或其他小部件?

c++ - --icon 选项不适用于 Qt > 5.5 中的 QApplication

c++ - 为什么 stack<const string> 不能在 g++ 中编译?

c++ - std::vector 大小在保留和填充后不会更新

c++ - CMAKE include_directories

java - 循环静态 Set-java