Ошибка многопоточного запуска Qt

У меня проблема с многопоточностью Qt. У меня есть класс, который я хочу в качестве темы

//protdata.cpp

class ProtData : public QObject
{
Q_OBJECT
private:
QList<ProtDataInputHandler *> _inputs;
public:
ProtData();
void addInput();
....
};

void ProtData::addInput(QIODevice *input, bool network_order)
{
_inputs.append(new ProtDataInputHandler());
}

У меня есть другой класс display.cpp, где я создаю экземпляр объекта protdata как поток, используя moveToThread ();

//display.cpp
...
QThread* newThread = new QThread();
_protdata->moveToThread(newThread);
newThread->start();
...

В какой-то момент в display.cpp:

//display.cpp
....
_protdata->addInput();

Когда я выполняю метод addInput, я получаю следующую ошибку:

QObject: Невозможно создать дочерние элементы для родителя, который находится в другом потоке.
(Родитель — ProtData (0x19bba50), родительский поток — QThread (0x19b3c18), текущий поток — QThread (0x1f08930).

Что не так? Я должен также переместить класс ProtDataInputHandler в newThread? Как?

Спасибо

0

Решение

AddInput должен вызываться только в procdata.cpp.
Вы можете использовать сигнал для вызова вашей функции, если вы определите ее как слот:

// display.h

signals :

void addInputSignal();

// display.cpp
QObject::connect(this,  SIGNAL(addInputSignal()), newThread,  SLOT(addInput()));
// ...
emit addInputSignal();

// protdata.h

public slots:

void addInput();
1

Другие решения

Попробуйте пометить свою функцию как Q_INVOKABLE:

Q_INVOKABLE void addInput();

Теперь вы можете использовать QMetaObject::invokeMethod для того, чтобы сделать перекрестный вызов метода. Переход к другому потоку не влияет на вызовы, которые вы делаете напрямую, но влияет на события и сигнальные вызовы, такие как этот:

QMetaObject::invokeMethod(_procdata, "addInput", Qt::AutoConnection);

Чтобы передать аргументы, вам нужно добавить дополнительные аргументы QMetaObject::invokeMethod, как правило, используя Q_ARG макрос.

0

Ваша проблема — эта строка в коде:

_inputs.append(new ProtDataInputHandler());

_inputs были созданы в главном потоке, когда ваши ProtData были созданы в основном потоке.

Однако вы вызываете метод addInput (), работающий с этим, после того, как ваш подкласс ProtData QObject был перемещен в другой поток.

Лучшее решение будет использовать механизм сигнального слота в Qt.

По сути, вы должны определить слот в вашем классе ProtData, а также сигнал. Вы отправите сигнал из addInput, и ваш соответствующий слот будет помещен в очередь цикла событий Qt для выполнения.

Затем вы должны установить соединение между сигналом и слотом в конструкторе ProtData.

Применяя всю эту теорию на практике, вы изменили бы свой код следующим образом:

//protdata.cpp

class ProtData : public QObject
{
Q_OBJECT
private:
QList<ProtDataInputHandler *> _inputs;
public:
explicit ProtData(QObject *parent = 0);
void addInput();
public signals:
void appendInput();
public slots:
void handleAppendInput();
....
};

ProtData::ProtData(QObject *parent)
: QObject(parent)
{
...
connect(this, SIGNAL(appendInput()), SLOT(handleAppendInput()));
...
}

void ProtData::handleAppendInput()
{
_inputs.append(new ProtDataInputHandler());
}

void ProtData::addInput(QIODevice *input, bool network_order)
{
emit appendInput();
}

Обратите внимание, что я также исправил другие проблемы в вашем коде:

  • Я сделал ваш конструктор явным, как и должно быть из-за равномерной инициализации с C ++ 11 и далее.

  • Вы забыли иметь родительский аргумент QObject, который назначен базовому классу, поэтому я также изменил его, имея значение по умолчанию «no parent», если оно не указано явно.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector