观察 QStringList 的新项目
Watch a QStringList for new items
我正在 QT 框架中开发数据记录器。我打算将日志字符串保存到文件中,并在单独的观察线程中打印到控制台。在那个单独的线程中,我需要观察我的 QStringList 是否添加了新项目。如果有新项目,我将它们从队列中取出并记录下来。我想知道 Qt 框架中使用的机制是什么。在 STD 库中,我使用 condition_variable
来完成这样的任务:
/*!
* \brief puts a \ref logline_t object at the end of the queue
* @param s object to be added to queue
*/
void CLogger::push_back(logline_t* s)
{
unique_lock<mutex> ul(m_mutex2);
s->queSize = m_data.size();
m_data.emplace_back(move(s));
m_cv.notify_all();
}
/*!
* \brief takes a \ref logline_t object from the beggining of the queue
* @return first \ref logline_t object
*/
CLogger::logline_t CLogger::pop_front()
{
unique_lock<mutex> ul(m_mutex2);
m_cv.wait(ul, [this]() { return !m_data.empty(); });
assert(m_data.front());
logline_t retVal = move(*m_data.front());
delete m_data.front();
m_data.front() = NULL;
m_data.pop_front();
return retVal;
}
m_cv
是条件变量对象。如何使用 QT 获取此功能?我敢打赌有很多更好的方法 :)。我将不胜感激所有帮助。
Ps: 我知道指针函数参数没有断言,这是一个旧代码...:P
在 Qt 中有几种方法可以进行通知。
信号与槽
信号和槽可以在线程间传递,连接时将连接类型设置为Qt::QueuedConnection or Qt::BlockingQueuedConnection。
您可能想要围绕 QStringList 创建一个包装器 class,以便修改可以触发其他 classes 侦听的信号。
QMutex 和 QWaitCondition
您可以使用 Qt 线程同步 classes QMutex and QWaitCondition to do the classic manual synchronisation like you have done previously. When using QMutex, the QMutexLocker 对于 QMutex 的作用域锁定和释放很有用。
下面是执行此信号和槽的示例。您可能想做自己的基准测试来测试这是否符合您的需要。另请注意,虽然信号和槽保证线程安全,但它们不保证消息将按照发送时的相同顺序出现。话虽这么说,我已经使用这种机制多年了,但它还没有发生在我身上。
首先,创建一对 类:
Loggee
// loggee.hpp
#ifndef LOGGEE_HPP
#define LOGGEE_HPP
#include <QObject>
class Loggee : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
void someEventHappened(int id);
signals:
void newLogLineNotify(QString const&);
};
#endif // LOGGEE_HPP
和 .cpp 文件:
#include "loggee.hpp"
void Loggee::someEventHappened(int id)
{
auto toLog = QString::number(id);
emit newLogLineNotify(toLog);
}
记录器
#ifndef LOGGER_HPP
#define LOGGER_HPP
#include <QObject>
class Logger : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
signals:
public slots:
void onLogEventHappened(QString const&);
};
#endif // LOGGER_HPP
和 .cpp 文件:
#include <QDebug>
#include <QThread>
#include "logger.hpp"
void Logger::onLogEventHappened(QString const& str)
{
qDebug() << QThread::currentThreadId() << str;
}
其余
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
#include <QTimer>
#include "logger.hpp"
#include "loggee.hpp"
int main(int argc, char** argv)
{
QCoreApplication a(argc, argv);
QThread t;
t.start();
Logger foo;
Loggee bar;
foo.moveToThread(&t);
QObject::connect(&bar, &Loggee::newLogLineNotify,
&foo, &Logger::onLogEventHappened,
Qt::AutoConnection);
qDebug() << "Current thread id: " << QThread::currentThreadId();
bar.someEventHappened(42);
QTimer::singleShot(3000, [&]{ bar.someEventHappened(43); });
return a.exec();
}
在这个演示中,我创建了一个 QThread
和一个 Logger
,将这个新 Logger
的槽的处理移到了这个新线程的事件循环中。然后我使用 Qt::AutoConnection
将 Loggee
的信号与 Logger
的插槽连接起来。这是默认设置,但我明确声明它是为了表明您可以更改它(即 Qt::QueuedConnection
,即使两个线程都在同一个线程中,它也会对插槽的执行进行排队)。
然后我让 Loggee
发出一个信号。它得到适当的调度并导致日志槽在接收方的线程中执行。
¹ emit
是 #define emit /*null*/
,所以你可以省略它
如果您只是在寻找与您一直在使用的 类 等效的 Qt:
std::mutex -> QMutex
std::condition_variable -> QWaitCondition
std::unique_lock -> QMutexLocker
我正在 QT 框架中开发数据记录器。我打算将日志字符串保存到文件中,并在单独的观察线程中打印到控制台。在那个单独的线程中,我需要观察我的 QStringList 是否添加了新项目。如果有新项目,我将它们从队列中取出并记录下来。我想知道 Qt 框架中使用的机制是什么。在 STD 库中,我使用 condition_variable
来完成这样的任务:
/*!
* \brief puts a \ref logline_t object at the end of the queue
* @param s object to be added to queue
*/
void CLogger::push_back(logline_t* s)
{
unique_lock<mutex> ul(m_mutex2);
s->queSize = m_data.size();
m_data.emplace_back(move(s));
m_cv.notify_all();
}
/*!
* \brief takes a \ref logline_t object from the beggining of the queue
* @return first \ref logline_t object
*/
CLogger::logline_t CLogger::pop_front()
{
unique_lock<mutex> ul(m_mutex2);
m_cv.wait(ul, [this]() { return !m_data.empty(); });
assert(m_data.front());
logline_t retVal = move(*m_data.front());
delete m_data.front();
m_data.front() = NULL;
m_data.pop_front();
return retVal;
}
m_cv
是条件变量对象。如何使用 QT 获取此功能?我敢打赌有很多更好的方法 :)。我将不胜感激所有帮助。
Ps: 我知道指针函数参数没有断言,这是一个旧代码...:P
在 Qt 中有几种方法可以进行通知。
信号与槽
信号和槽可以在线程间传递,连接时将连接类型设置为Qt::QueuedConnection or Qt::BlockingQueuedConnection。
您可能想要围绕 QStringList 创建一个包装器 class,以便修改可以触发其他 classes 侦听的信号。
QMutex 和 QWaitCondition
您可以使用 Qt 线程同步 classes QMutex and QWaitCondition to do the classic manual synchronisation like you have done previously. When using QMutex, the QMutexLocker 对于 QMutex 的作用域锁定和释放很有用。
下面是执行此信号和槽的示例。您可能想做自己的基准测试来测试这是否符合您的需要。另请注意,虽然信号和槽保证线程安全,但它们不保证消息将按照发送时的相同顺序出现。话虽这么说,我已经使用这种机制多年了,但它还没有发生在我身上。
首先,创建一对 类:
Loggee
// loggee.hpp
#ifndef LOGGEE_HPP
#define LOGGEE_HPP
#include <QObject>
class Loggee : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
void someEventHappened(int id);
signals:
void newLogLineNotify(QString const&);
};
#endif // LOGGEE_HPP
和 .cpp 文件:
#include "loggee.hpp"
void Loggee::someEventHappened(int id)
{
auto toLog = QString::number(id);
emit newLogLineNotify(toLog);
}
记录器
#ifndef LOGGER_HPP
#define LOGGER_HPP
#include <QObject>
class Logger : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
signals:
public slots:
void onLogEventHappened(QString const&);
};
#endif // LOGGER_HPP
和 .cpp 文件:
#include <QDebug>
#include <QThread>
#include "logger.hpp"
void Logger::onLogEventHappened(QString const& str)
{
qDebug() << QThread::currentThreadId() << str;
}
其余
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
#include <QTimer>
#include "logger.hpp"
#include "loggee.hpp"
int main(int argc, char** argv)
{
QCoreApplication a(argc, argv);
QThread t;
t.start();
Logger foo;
Loggee bar;
foo.moveToThread(&t);
QObject::connect(&bar, &Loggee::newLogLineNotify,
&foo, &Logger::onLogEventHappened,
Qt::AutoConnection);
qDebug() << "Current thread id: " << QThread::currentThreadId();
bar.someEventHappened(42);
QTimer::singleShot(3000, [&]{ bar.someEventHappened(43); });
return a.exec();
}
在这个演示中,我创建了一个 QThread
和一个 Logger
,将这个新 Logger
的槽的处理移到了这个新线程的事件循环中。然后我使用 Qt::AutoConnection
将 Loggee
的信号与 Logger
的插槽连接起来。这是默认设置,但我明确声明它是为了表明您可以更改它(即 Qt::QueuedConnection
,即使两个线程都在同一个线程中,它也会对插槽的执行进行排队)。
然后我让 Loggee
发出一个信号。它得到适当的调度并导致日志槽在接收方的线程中执行。
¹ emit
是 #define emit /*null*/
,所以你可以省略它
如果您只是在寻找与您一直在使用的 类 等效的 Qt:
std::mutex -> QMutex
std::condition_variable -> QWaitCondition
std::unique_lock -> QMutexLocker