【问题标题】:QThread Vs QFutureQThread 与 QFuture
【发布时间】:2013-12-29 06:51:39
【问题描述】:

哪个更合适:QThread 还是 QFuture ? 我正在尝试在 QThread 中传递 QNetWorkAccessManager,但这会导致父线程和子线程出错:/

QObject:无法为不同线程中的父级创建子级。 (Parent是QNetworkAccessManager(0xc996cf8),parent的线程是QThread(0xaba48d8),当前线程是Citizen(0xca7ae08)

m_networkManger = new QNetworkAccessManager(this);
m_thread = new QThread();

m_data = new LoadData(m_labelsList, m_parserType, argUrl, m_networkManger);
m_data->moveToThread(m_thread);

connect(m_thread, SIGNAL(started()), m_data, SLOT(process()));
connect(m_thread, SIGNAL(finished()), m_thread, SLOT(deleteLater()));

m_thread->start();

使用QFuture可以解决问题吗?

【问题讨论】:

  • 要实现的重要细节:QThread 是线程控制器,它必须具有与其控制的线程不同的线程亲和性。子 QObject 必须与其父 QObject 具有相同的线程亲缘关系。
  • 你也必须在网络管理器上做 moveToThread

标签: qt qthread


【解决方案1】:

我的第一个想法是为什么要将 networkManager 移动到不同的线程?

无论如何,您看到的问题是,当您将对象移动到新线程时,它会移动该对象及其子对象。

您创建 m_networkManager 并将“this”传递给它,使该对象成为其父对象。无论该对象是什么,它都将驻留在原始线程上。您不能将子对象移动到与其父对象不同的线程。

因此,在创建 QNetworkAccessManager 时移除父对象 'this'。

m_networkManger = new QNetworkAccessManager;

确保您处理删除 networkManager,因为它不再是父级。

【讨论】:

  • 另外,在删除父级时,添加connect(m_thread, SIGNAL(finished()), m_networkManger, SLOT(deleteLater())); 可能是个好主意
【解决方案2】:

移动到其他线程的对象不能有父对象。 Qt 的设计方式是整个对象树必须在一个线程中(对象连同其所有子对象一起移动到另一个线程)。

如果对象有父对象 moveToThread 将失败(什么都不做,只会在日志中打印错误)。

在这种情况下,QFuture 不会改变任何东西。

请注意,您可以在对象所属的不同线程中运行对象方法。如果对象属于某个线程,则意味着该对象的连接槽将倾向于从该线程调用(仅当连接类型为Qt::DirectConnection槽时才能从不同线程调用)。

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2020-06-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多