Передача через QModelIndex кросс-потокового соединения - PullRequest
2 голосов
/ 11 июля 2011
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'
(Убедитесь, что QModelIndex зарегистрирован с помощью qRegisterMetaType ().)

Что мне делать? так как мой SLOT(rowAdded()) не требует 3 аргументов SIGNAL(rowsInserted(QModelIndex,int,int)), я должен сделать еще один сигнал, например rowInserted(), и излучать его всякий раз, когда я излучаю rowsInserted(QModelIndex,int,int), и использовать вместо этого SIGNAL для этой совместной связи

Вы можете спросить, почему я использую сигналы, подобные модели, такие как rowsInserted(QModelIndex,int,int) в структуре данных таблицы. потому что у меня также есть модель, которая связана с этой таблицей. который также будет обновляться строка за строкой. однако я думаю, что это неважно в этом отношении.

Ответы [ 2 ]

2 голосов
/ 25 июня 2016

Я знаю, что уже довольно поздно, но я хотел убедиться, что кто-то упомянул об этом: QModelIndex не предназначен для постановки в очередь, по той же причине, по которой он не предназначен для хранения и последующего использования другими способами. То есть, если модель изменится до использования QModelIndex, вы получите неопределенное поведение. Если вам нужны события в очереди с модельными индексами, вам, вероятно, следует использовать QPersistentModelIndex. На самом деле не имеет отношения к исходному вопросу, но может пригодиться тому, кто приземлится здесь.

2 голосов
/ 11 июля 2011

Перед отправкой сигнала через границу потока с нетривиальным типом аргумента (например, 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

...