c++ - QMetaObject::invokeMethod() 在用于调用 QListWidget::addItem() 时返回 false

标签 c++ qt thread-safety

我正在尝试使用 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/

相关文章:

c++ - 体系结构 x86_64 dylib 链接的 undefined symbol

c++ - 有没有一种方法可以在不污染命名空间的情况下使用 boost::assign 运算符?

c++ - QVector 总是推回 0?

python - 线程本地是否意味着线程安全?

java - Trove 库是线程安全的吗?

c++ - 如何在 Boost Unit 中正确定义派生单位

c++ - sqrt(int_value + 0.0) -- 它有目的吗?

multithreading - C++11 线程在构造函数中初始化以执行方法

qt - 使用 sqlite 使用具有唯一列的 fts3 创建虚拟表不会保持唯一

java - JCheckBox.isSelected() 线程安全吗?