2013-08-04 13 views
2

QMetaObject :: invokeMethod를 사용하여 threadsafe 방식으로 주 스레드가 소유 한 QListWidget에 항목을 추가하려고합니다.().QMetaObject :: invokeMethod()는 QListWidget :: addItem()을 호출 할 때 false를 반환합니다.

QMetaObject :: invokeMethod()이 작동하고 나는 (일반 전화를 사용할 때 QListWidget에)가 true를 돌려하지만 addItem를을 (전화를 사용할 때이 코드에서 볼 수 있듯이,)가 false를 돌려 :

void BlockingInvokeStringArg(QObject* widget, const char* functionName, const string& arg = "") 
{ 
    QString argAsQString(arg.c_str()); 
    QGenericArgument genericArg = arg.empty() ? QGenericArgument() : Q_ARG(QString, argAsQString); 
    if (!QMetaObject::invokeMethod(widget, functionName, Qt::BlockingQueuedConnection, genericArg)) 
    { 
     throw runtime_error("QMetaObject::invokeMethod() returned false"); 
    } 
} 

void BacktestGui::on_buttonRunBacktest_clicked() 
{ 
    auto runBacktest = [&]() 
    { 
     // Does not throw: 
     BlockingInvokeStringArg(m_ui.listSymbols, "clear"); 
     // Throws: 
     BlockingInvokeStringArg(m_ui.listSymbols, "addItem", "ItemName"); 
     // Does not throw but may be thread-unsafe due to a background thread interacting with a GUI component owned by the main thread: 
     m_ui.listSymbols->addItem("ItemName"); 
    }; 
    QtConcurrent::run(runBacktest); 
} 

QListWidget에서 clear()를 호출 할 때 QMetaObject :: invokeMethod()가 true를 반환하지만 addItem()을 호출 할 때 false를 반환하는 이유는 무엇입니까?

QMetaObject :: invokeMethod()를 사용하여 addItem()을 호출 할 수없는 경우 백그라운드 스레드에서 QListWidget에 항목을 추가하는 데 필요한 threadsafe 대안을 알고 있습니까?

답변

3

invokeMethod()는 신호 또는 슬롯을 호출 할 수 있습니다. QListWidget :: clear()는 슬롯이므로 작동합니다. QListWidget :: addItem()은 슬롯이 아니므로 호출 할 수 없습니다.

해결책은 간단합니다. QListWidget을 인수로 취하고 addItem()을 호출하고 해당 슬롯을 호출하는 슬롯을 작성하십시오.