【问题标题】:QMetaObject::invokeMethod() returning false when used to call QListWidget::addItem()QMetaObject::invokeMethod() 用于调用 QListWidget::addItem() 时返回 false
【发布时间】:2013-08-04 10:22:24
【问题描述】:

我正在尝试使用 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 添加项目的线程安全替代方法吗?

【问题讨论】:

    标签: c++ qt thread-safety


    【解决方案1】:

    invokeMethod() 能够调用信号或槽。 QListWidget::clear() 是一个插槽,因此可以工作。 QListWidget::addItem() 不是一个槽,因此你不能调用它。

    解决方案很简单。编写一个将 QListWidget 作为参数并在其上调用 addItem() 的插槽,然后调用该插槽。

    【讨论】:

      猜你喜欢
      • 2010-12-30
      • 2021-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多