我正在尝试使用 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() 返回真,而在调用 addItem() 时返回假?
如果 QMetaObject::invokeMethod() 不能用于调用 addItem(),您知道从后台线程向 QListWidget 添加项目的线程安全替代方法吗?
最佳答案
invokeMethod() 能够调用信号或槽。 QListWidget::clear() 是一个插槽,因此可以正常工作。 QListWidget::addItem() 不是插槽,因此您不能调用它。
解决方法很简单。编写一个将 QListWidget 作为参数并调用 addItem() 的插槽,然后调用该插槽。
关于c++ - QMetaObject::invokeMethod() 在用于调用 QListWidget::addItem() 时返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18039048/