QMetaObject::invokeMethod() を使用して、スレッドセーフな方法でバックグラウンド スレッドからメイン スレッドが所有する QListWidget に項目を追加しようとしています。
QMetaObject::invokeMethod() は機能し、QListWidget で clear() を呼び出すために使用すると 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 にアイテムを追加するためのスレッドセーフな代替手段を知っていますか?