2014-01-10 142 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其中i實例使用moveToThread()的protdata對象作爲線程的類;

//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

嘗試標記你的函數爲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。

但是,在您的ProtData QObject子類被移動到另一個線程後,您調用addInput()對此進行操作。

最好的解決方案是在Qt中使用signal-slot mechanism

基本上,你可以在你的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」值時,我也修改了它。