moveToThread与Qt中的QThread派生 [英] moveToThread vs deriving from QThread in Qt

查看:92
本文介绍了moveToThread与Qt中的QThread派生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么时候应该优先使用moveToThread而不是子类QThread?

When should moveToThread be preferred over subclassing QThread?

此链接显示这两种方法均有效.我应该在哪两个基础上决定要使用什么?

This link shows that both methods work. On what basis should I decide what to use from those two?

推荐答案

我将重点介绍两种方法之间的差异.没有一个适合所有用例的通用答案,因此最好准确地了解它们是什么,以便选择最适合您的用例的东西.

I would focus on the differences between the two methods. There isn't a general answer that fits all use cases, so it's good to understand exactly what they are to choose the best that fits your case.

moveToThread()用于控制对象的线程亲和力,这基本上意味着设置对象将发出信号的线程(或更佳的Qt事件循环)并且其插槽将被执行.

moveToThread() is used to control the object's thread affinity, which basically means setting the thread (or better the Qt event loop) from which the object will emit signals and its slots will be executed.

如您链接的文档中所示,此代码可用于在不同线程上运行代码,基本上是创建 dummy worker ,将代码编写为在公共插槽中运行 strong>(在示例中为 doWork()插槽),然后使用 moveToThread 将其移至其他事件循环.

As shown in the documentation you linked, this can be used to run code on a different thread, basically creating a dummy worker, writing the code to run in a public slot (in the example the doWork() slot) and then using moveToThread to move it to a different event loop.

然后,触发连接到该插槽的信号.由于发出信号的对象(在示例中为 Controller )位于不同的线程中,并且该信号通过队列连接连接到我们的doWork方法,因此doWork方法将在worker中执行线程.

Then, a signal connected to that slot is fired. Since the object that emits the signal (the Controller in the example) lives in a different thread, and the signal is connected to our doWork method with a queued connection, the doWork method will be executed in the worker thread.

关键是要创建一个由工作线程运行的新事件循环.因此,一旦doWork插槽启动,整个事件循环将一直忙碌直到退出,这意味着传入的信号将被排队.

The key here is that you are creating a new event loop, run by the worker thread. Hence, once the doWork slot has started, the whole event loop will be busy until it exits, and this means that incoming signals will be queued.

Qt文档中描述的另一种方法是将QThread子类化.在这种情况下,将覆盖QThread :: run()方法的默认实现,该方法创建一个事件循环,以运行其他内容.

The other method described in Qt's documentation is subclassing QThread. In this case, one overrides the default implementation of the QThread::run() method, which creates an event loop, to run something else.

这种方法本身没有什么问题,尽管有很多问题.

There's nothing wrong with this approach itself, although there are several catches.

首先,编写不安全的代码非常容易,因为 run()方法是该类中唯一可以在另一个线程上实际运行的方法.

First of all, it is very easy to write unsafe code, because the run() method is the only one in that class that will be actually run on another thread.

例如,如果您有一个成员变量,该成员变量在构造函数中初始化,然后在 run()方法中使用,则该成员将在调用者的线程中初始化,然后在新线程.

If as an example, you have a member variable that you initialize in the constructor and then use in the run() method, your member is initialized in the thread of the caller and then used in the new thread.

对于可以从调用方或在run()内部调用的任何公共方法,都是相同的情况.

Same story for any public method that could be called either from the caller or inside run().

插槽也会从调用者的线程中执行,(除非您做为 moveToThread(this)确实很奇怪),否则会引起更多混乱.

Also slots would be executed from the caller's thread, (unless you do something really weird as moveToThread(this)) leading to extra confusion.

因此,有可能,但是您确实需要这种方法,并且必须格外注意.

So, it is possible, but you really are on your own with this approach and you must pay extra attention.

这两种方法当然都有替代方法,具体取决于您的需求.如果您只需要在GUI线程运行时在后台运行一些代码,则可以考虑使用 QtConcurrent :: run().

There are of course alternatives to both approaches, depending on what you need. If you just need to run some code in background while your GUI thread is running you may consider using QtConcurrent::run().

但是,请记住,QtConcurrent将使用全局 QThreadPool .如果整个池繁忙(意味着池中没有可用的线程),则您的代码将不会立即运行.

However, keep in mind that QtConcurrent will use the global QThreadPool. If the whole pool is busy (meaning there aren't available threads in the pool), your code will not run immediately.

如果您至少使用C ++ 11,则另一种选择是使用较低级别的API,例如 std :: thread .

Another alternative, if you are at the least on C++11, is to use a lower level API such as std::thread.

这篇关于moveToThread与Qt中的QThread派生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆