gpt4 book ai didi

c++ - 槽中的 QMutex

转载 作者:行者123 更新时间:2023-11-28 06:26:21 30 4
gpt4 key购买 nike

假设有如下QT代码(QT 5.3.1):

void SenderClass::runSignal()
{
emit mySignal();
}

void ReceiverClass::ReceiverClass()
{
...
connect (senderClassRef, SIGNAL(mySignal()), this, SLOT(mySlot()) );
}

void ReceiverClass::mySlot()
{
//Long operation executions
Sleep(1000);
qDebug() << "1";
Sleep(1000);
qDebug() << "2";
Sleep(1000);
qDebug() << "3";
}

连续调用 runSignal() 控制台会显示如下内容:

1 2 1 3 2 3

这两个类在同一个线程中。我必须在插槽中使用 QMutexLocker 吗?或者是否有另一种方法来获得有序输出,例如:

1 2 3 1 2 3

因此,如果仍有一个正在执行,则阻止调用 mySlot() 函数。

更新

下面是一段真实的代码片段。发件人:

//Sender.h

#include <QtWidgets/QWidget>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTextBrowser>

class Receiver;

class Sender : public QWidget
{
Q_OBJECT

public:
Sender(QWidget *parent = 0);

QPushButton *pushButton;
QTextBrowser *textBrowser;
Receiver* receiver;

signals:
void buttonClickedSignal();

public slots:
void ButtonClickedSlot();
};

//Sender.cpp

#include "Sender.h"
#include "Receiver.h"

#include <QObject>

Sender::Sender(QWidget *parent)
: QWidget(parent)
{
pushButton = new QPushButton(this);
pushButton->setObjectName(QStringLiteral("pushButton"));
pushButton->setGeometry(QRect(150, 30, 75, 23));
pushButton->setText("Button");
textBrowser = new QTextBrowser(this);
textBrowser->setObjectName(QStringLiteral("textBrowser"));
textBrowser->setGeometry(QRect(50, 90, 256, 192));

receiver = new Receiver(this);

QObject::connect(pushButton, SIGNAL(clicked()), this, SLOT(ButtonClickedSlot()));
}

void Sender::ButtonClickedSlot()
{
emit buttonClickedSignal();
}

接收者:

//Receiver.h
#include "Sender.h"

class Receiver : QObject
{
Q_OBJECT

public:
Receiver(Sender *sender);

Sender *m_sender;

public slots:
void ReceiverSlot();
};

//Receiver.cpp
#include "Receiver.h"

#include <QObject>
#include <QThread>
#include <QApplication>

Receiver::Receiver(Sender *sender)
{
m_sender = sender;

QObject::connect(m_sender, SIGNAL(buttonClickedSignal()), this, SLOT(ReceiverSlot()), Qt::QueuedConnection);
}

void Receiver::ReceiverSlot()
{
m_sender->textBrowser->append("1");
QThread::msleep(100);
qApp->processEvents();
m_sender->textBrowser->append("2");
QThread::msleep(100);
qApp->processEvents();
m_sender->textBrowser->append("3");
QThread::msleep(100);
qApp->processEvents();
m_sender->textBrowser->append("4");
QThread::msleep(100);
qApp->processEvents();
}

即使设置了 QueuedConnection,快速单击按钮也会导致 QTextBrowser 中的数字不连续。

Output

更新 2

我想要实现的是对 ReceiverSlot 的排队访问。用户可以随意点击按钮(在他想要的时候以任何速度)。 ReceiverSlot 不能错过任何事件。我需要某种事件排队,以便始终执行 ReceiverSlot 中的(长)操作,可能会延迟,但会执行。

最佳答案

摆脱 QApplication::processEvents 并将卡住 GUI 的长操作移至新线程。例如,您可以使用移动到新线程的工作对象。有一个good example of this in the docs .

您还应该阅读 this了解有关 Qt 中线程和事件的更多信息。与您在 forcing event dispatching 中解释的情况完全相同部分:

“通过其他路径”重新进入事件循环时要非常小心:它可能会导致不需要的递归!让我们回到 Button 示例。如果我们在 doWork() 槽中调用 QCoreApplication::processEvents(),并且用户再次点击按钮,doWork() 槽将再次被调用:

  • main(int, char **) QApplication::exec()
  • […]
  • QWidget::event(QEvent *)
  • Button::mousePressEvent(QMouseEvent *)
  • 按钮::点击()
  • […]
  • Worker::doWork()//首先,内部调用
  • QCoreApplication::processEvents()//我们手动调度事件并......
  • […]
  • QWidget::event(QEvent * )//另一个鼠标点击被发送到按钮……
  • Button::mousePressEvent(QMouseEvent *)
  • Button::clicked()//再次发出 clicked() ......
  • […]
  • Worker::doWork()//该死!我们已经递归到我们的插槽中。

通常,您希望避免 QApplication::processEvents 并创建本地事件循环。如果你的代码中有这些,那么你应该重新设计它,这样你就不必使用它们了。

文档中的 Worker 对象示例:

 class Worker : public QObject
{
Q_OBJECT
QThread workerThread;

public slots:
void doWork(const QString &parameter) {
// ...
emit resultReady(result);
}

signals:
void resultReady(const QString &result);
};

class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};

关于c++ - 槽中的 QMutex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28473563/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com