2014-01-10 6 views
0

У меня проблема с многопоточным 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: Cannot create children for a parent that is in a different thread. (Parent is ProtData(0x19bba50), parent's thread is QThread(0x19b3c18), current thread is QThread(0x1f08930)

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

Благодаря

ответ

1

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(); 
0

Try испачкать функцию Q_INVOKABLE:

Q_INVOKABLE void addInput(); 

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

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

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

0

Ваш вопрос эта строка в коде:

_inputs.append(new ProtDataInputHandler()); 

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

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

Лучшим решением было бы использовать signal-slot mechanism в 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, назначенный базовому классу, поэтому я также внесла исправление, имея значение по умолчанию «без родителя», если оно явно не указано.