我正在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
发布于 2016-10-14 21:17:59
这是一个做这个信号和插槽的例子。您可能想做自己的基准测试,以测试这是否符合您的需要。还请注意,虽然信号和插槽保证线程安全,但它们不能保证消息以相同的顺序出现。尽管如此,我已经使用这个机制多年了,但它还没有发生在我身上。
首先,创建两个类:
洛吉
// 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
的时隙连接起来。这是默认的,但我明确地说明了这一点,以表明您可以更改它(即,如果两个线程都驻留在同一个线程中,就可以将该插槽的执行排在队列中)。
然后,我使Loggee
发出一个信号。它得到正确的调度,并导致日志槽在接收器的线程中执行。
emit
是#define emit /*null*/
,所以如果愿意,可以省略它。
发布于 2016-10-14 21:01:39
在Qt中有几种执行通知的方法。
信号和插槽
可以在线程之间发送信号和插槽,在建立连接时,将连接类型设置为Qt::QueuedConnection或Qt::BlockingQueuedConnection。
您可能希望在QStringList周围创建一个包装类,以便修改可以触发其他类侦听的信号。
QMutex和QWaitCondition
您可以像以前一样使用Qt线程同步类QMutex和QWaitCondition进行经典的手动同步。当使用QMutex时,QMutexLocker对于范围锁定和QMutex的发布非常有用。
发布于 2016-10-15 09:45:23
如果您只是在寻找您一直在使用的类的Qt等价物:
std::mutex -> QMutex
std::condition_variable -> QWaitCondition
std::unique_lock -> QMutexLocker
https://stackoverflow.com/questions/40050318
复制相似问题