【问题标题】:Accessing Qt widget thread safe访问 Qt 小部件线程安全
【发布时间】:2015-05-06 18:05:46
【问题描述】:

我使用 QPlainTextEdit 来显示一些文本。此文本将在 ui(main) 线程之外的另一个线程中修改(附加),并向小部件发送信号

connect(this, SIGNAL(addText(QString)), mUi->plainTextEditLog, SLOT(appendPlainText(QString)));

...
emit addText(QString::fromStdString(someString));
...

另一个线程正在读取此 PlainTextEdit 的文本并将其写入文件

QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
    return;
}
file.write(mUi->plainTextEditLog->toPlainText().toUtf8());
file.close();

据我所知,Qt 小部件不是线程安全的。我想过一个互斥锁来锁定写入信号发出,但这不会真正锁定它,因为它只是异步发送信号。

我使用信号的原因是可以从多个线程调用写入方法,而互斥体在这种情况下没有帮助,但信号完美。

第二个想法是将文本也存储在我的班级中,并通过互斥锁定字符串。但我不确定这是否非常有效,因为不仅有明文编辑需要修改,还有字符串作为副本。

【问题讨论】:

  • 选择第二种方法,当一切正常并且真的太慢时担心效率。
  • “我想到了一个互斥锁来锁定写入信号发出”
  • 检查您的 Qt 文档并搜索:Qt::QueuedConnection
  • 通过信号将字符串发送到另一个线程并在那里写入。跨线程信号/插槽连接是 /queued/ 并且参数被复制,即在这种情况下您不必担心锁定。 (消息传递范式)

标签: c++ multithreading qt


【解决方案1】:

本质上,只要您在将信号从属于另一个线程(请参阅QObject::moveToThread)的对象连接到小部件(必须属于主gui 线程),然后发出信号将是一个异步的“即发即弃”调用。您还可以通过指定它是阻塞队列连接来使调用同步,但除非您确实需要,否则我不建议这样做。

Qt 中的线程模型需要花一点时间来理解,但您会越来越喜欢多线程代码中提供的简单信号和槽,以及不再需要使用互斥锁来保护其数据的代码片段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多