【问题标题】:Passing QModelIndex cross Thread queued connection传递 QModelIndex 跨线程排队连接
【发布时间】:2011-07-11 19:32:48
【问题描述】:
WMIQuery::wmiquery(WMI::WMITable* table, const QString& query, WMI::ProgressIndicator* progressIndicator)

这是函数签名。我通过QtConcurrent::run调用它

QFuture<quint32> future = QtConcurrent::run(WMI::WMIQuery::wmiquery, _table, query);

架构非常简单。 查询将返回的预期行数是已知的。 查询并行运行,并在每条记录上提取一行添加到table: WMI::WMITable* WMI::WMITable 是一个简单的 QObject 表数据结构。 它在添加行时发出rowsAboutToBeInserted(QModelIndex, int, int)rowsInserted(QModelIndex, int, int)

另一方面,ProgressIndicator 在主线程上实例化,table 被传递给它的 ctor。它获取从WMI::WMIQuery::wmiquery()ProgressIndicator::setRecordCount(quint64 count) 的预期总行数。 它有一个插槽rowAdded(),它通过做一些简单的数学计算得出100分的进度。在它的ctor中它连接了

connect(_table, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowAdded()));

我的想法。由于WMI::WMIQuery::wmiquery() 我在不同的线程(QThreadPool)上运行,此连接是跨线程排队连接。我说的对吗?

我在运行时收到以下错误

QObject::connect: 无法将“QModelIndex”类型的参数排队
(确保使用 qRegisterMetaType() 注册 'QModelIndex'。)

我该怎么办?因为我的SLOT(rowAdded()) 不需要SIGNAL(rowsInserted(QModelIndex,int,int)) 的3 个参数,我是否应该发出另一个信号,如rowInserted() 并在我发出rowsInserted(QModelIndex,int,int) 时发出它,并使用这个SIGNAL 而不是这个连接

你可能会问为什么我在表数据结构中使用类似rowsInserted(QModelIndex,int,int) 的信号模型。因为我也有一个连接到这个表的模型。这也将逐行更新。但是我认为这在这方面是不重要的。

【问题讨论】:

    标签: qt threadpool signals-slots qmodelindex


    【解决方案1】:

    在使用非平凡参数类型(如QModelIndex)跨线程边界发出信号之前,您必须首先调用它:

    qRegisterMetaType<QModelIndex>("QModelIndex");
    

    这让 Qt 能够跨线程边界发出信号。

    通常您会在main() 或仅运行一次的地方执行此操作,调用emit,但您的QApplication 已被实例化。

    这只对非平凡的类型是必需的。例如,这样的信号不会要求您致电qRegisterMetaType()

    signals:
       void mySignal(int foo, int bar);
    

    但是像这样的信号确实需要qRegisterMetaType()

    signals:
       void mySignal(QModelIndex);
    

    有关详细信息,请参阅此处的 Qt 文档:http://doc.qt.nokia.com/latest/qmetatype.html#qRegisterMetaType

    【讨论】:

    • 另一种选择是从您发出的信号中删除QModelIndexints,因为它们无论如何都不会在插槽rowAdded() 中收到。
    • 是的,正如我在问题中提到的那样,我已经尝试过这种方式。它奏效了。
    • 还有qRegisterMetaType&lt;QModelIndex&gt;("QModelIndex") 中的额外开销是什么?那应该解决那个问题吗?这是一种真正的方式吗?还是一个糟糕的黑客?
    • 使用qRegisterMetaType() 是真正的方法。这不是黑客。我从来没有注意到任何开销。效果很好。
    【解决方案2】:

    我知道这已经很晚了,但我想确定有人提到它:QModelIndex 并不意味着要排队,因为同样的原因,它也不意味着存储和以后以其他方式使用。也就是说,如果模型在您使用 QModelIndex 之前发生更改,您将获得未定义的行为。如果您需要带有模型索引的队列事件,您可能应该使用 QPersistentModelIndex。与原始问题并不真正相关,但可能对登陆这里的人有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-07
      • 2011-07-01
      • 1970-01-01
      相关资源
      最近更新 更多