我有这样的课
class GUI : public QWidget, public QThread
Run Code Online (Sandbox Code Playgroud)
当我执行上述操作时,我会收到有关连接信号的错误.The error says Reference to "connect" is ambiguous.有没有办法从两者继承?
谢谢
我们什么时候在线程应用程序中使用每个函数调用.给定两个函数fun1()和fun2()在同一个类中定义处理数据到缓冲区的读/写(队列操作).实现对这些的多线程.我们必须在一个单独的线程中运行这两个函数.现在假设第一个函数read在其线程的开头被调用.
最好在第一个函数线程的开头使用moveTothread(第二个线程)进行函数写入
要么
在新线程类中定义第二个函数,并在第一个线程的开头调用该线程.
我实现了一个类,它可以通过QQueue将数据写入串口,并通过插槽读取.我使用QAsyncSerial来反过来使用boost :: asio和回调.该类被移动到一个线程,当QThread发出"started()"时,它的start()方法被执行
问题是我使用forever {}和QWaitCondition在start() - 方法中使QQueue出列.当这个运行时(显然会永远运行),连接到QAsyncSerial的dataReceived信号的插槽无法被调用,因此我从未从串口读取任何内容.
解决这个问题的常用方法是什么?
SerialPortHandler::SerialPortHandler(SerialPort serialPort, QObject *parent) : QObject(parent), serialPort(serialPort)
{
m_enqueueMessageMutex = new QMutex();
m_messageQueue = new QQueue<BaseMessage*>();
m_waitCondition = new QWaitCondition();
serial.open(serialPort.deviceName(), 2400);
connect(&serial, SIGNAL(dataReceived(QByteArray)), this, SLOT(serialSlotReceivedData(QByteArray)));
}
void SerialPortHandler::serialSlotReceivedData(QByteArray line)
{
qDebug() << QString(line).toAscii();
}
void SerialPortHandler::sendTestPing()
{
PingMessage *msg = new PingMessage();
enqueueMessage(msg);
}
void SerialPortHandler::enqueueMessage(BaseMessage *msg)
{
QMutexLocker locker(m_enqueueMessageMutex);
m_messageQueue->enqueue(msg);
m_waitCondition->wakeAll();
}
void SerialPortHandler::start()
{
if (!serial.isOpen())
return;
forever {
m_enqueueMessageMutex->lock();
if (m_messageQueue->isEmpty())
m_waitCondition->wait(m_enqueueMessageMutex);
BaseMessage *msg = m_messageQueue->dequeue();
serial.write(msg->encodeForWriting());
m_enqueueMessageMutex->unlock(); …Run Code Online (Sandbox Code Playgroud) 如何在睡眠时唤醒QThread?
我有一个在后台运行的线程,现在然后醒来并做一些小事情,但是如果我想以受控方式停止该线程,我必须等待他自己醒来以便让他退出 由于他睡得很久,这可能会非常烦人.
这是一个显示基本问题的示例代码.
让我们从在这个例子中休眠5秒然后只打印一个点的线程开始.
#include <QDebug>
#include "TestThread.h"
void TestThread::run()
{
running = true;
while(running == true)
{
qDebug() << ".";
QThread::sleep(5);
}
qDebug() << "Exit";
}
void TestThread::stop()
{
running = false;
}
Run Code Online (Sandbox Code Playgroud)
然后我们有主要启动线程然后杀死他.
#include <QDebug>
#include "TestThread.h"
int main(int argc, char *argv[])
{
qDebug() << "Start test:";
TestThread *tt = new TestThread();
tt->start();
sleep(2);
tt->stop();
tt->wait();
delete tt;
}
Run Code Online (Sandbox Code Playgroud)
问题是tt-> wait(); 必须等待线程正在睡觉的5s.我可以称之为"从睡眠中醒来",这样他就可以继续.
或者有更好的方法吗?
/谢谢
更新我使用QMutex和tryLock:
#include <QDebug>
#include "TestThread.h"
QMutex sleepMutex;
void TestThread::run()
{
qDebug() << …Run Code Online (Sandbox Code Playgroud) 在这里提出这个问题之前,我已经想了很多并阅读了很多文章.这些文章都没有给我一个正确的答案.
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
Run Code Online (Sandbox Code Playgroud)
Worker对象具有新线程的亲和力.
1> Worker完成信号将调用线程上的quit().这将结束线程的事件循环并启动线程完成信号.
2> Worker完成信号连接到worker deleteLater().根据deleteLater()文档
**安排此对象删除.当控制返回到事件循环时,将删除该对象.如果事件循环>未运行
当调用此函数时(例如,在QCoreApplication :: exec()之前在对象上调用deleteLater()),一旦启动事件循环,该对象将被删除.
注意,进入和离开新的事件循环(例如,通过打开模态对话框)将不执行延迟删除; 对于要删除的对象,控件必须返回到调用deleteLater()的事件循环.
注意:不止一次调用此函数是安全的; 在传递第一个延迟删除事件时,将从事件队列中删除该对象的任何挂起事件.**
因此,当没有eventloop时,由于线程已经退出并且它已经提升了完成的信号,我们将不再再次启动相同的线程.在这种情况下,将永远不会处理deleteLater(),因为事件循环不存在,并且根本不会删除worker对象.这不会造成内存泄漏吗?
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
Run Code Online (Sandbox Code Playgroud)
如果我们认为交换这两行将解决问题,那么我还有另外一个问题.QT明确指出,在发出信号时调用插槽的顺序是不确定的
上面提到的文章链接中有很多评论.即便是作者也无法完全回答这个问题
我试图了解如何使用从Qthread返回到启动的Gui接口的信令.
设置:我有一个需要几乎无限期运行的进程(模拟)(或者至少在很长一段时间内运行).当它运行时,它执行各种计算,并且一些结果必须被发送回GUI,将实时适当地显示它们.我正在使用PyQt进行GUI.我最初尝试使用python的线程模块,然后在SO和其他地方阅读了几个帖子后切换到QThreads.
根据Qt博客上的这篇文章你做错了,使用QThread的首选方法是创建一个QObject,然后将其移动到Qthread.所以我在PyQt中跟随了关于QThread的onBackground线程的建议">这个问题并尝试了一个简单的测试应用程序(下面的代码):它打开了一个简单的GUI,让你启动后台进程,并且它发布了更新步骤值一个旋转盒.
但它不起作用.GUI永远不会更新.我究竟做错了什么?
import time, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class SimulRunner(QObject):
'Object managing the simulation'
stepIncreased = pyqtSignal(int, name = 'stepIncreased')
def __init__(self):
super(SimulRunner, self).__init__()
self._step = 0
self._isRunning = True
self._maxSteps = 20
def longRunning(self):
while self._step < self._maxSteps and self._isRunning == True:
self._step += 1
self.stepIncreased.emit(self._step)
time.sleep(0.1)
def stop(self):
self._isRunning = False
class SimulationUi(QDialog):
'PyQt interface'
def __init__(self):
super(SimulationUi, self).__init__()
self.goButton = QPushButton('Go')
self.stopButton = QPushButton('Stop')
self.currentStep = QSpinBox()
self.layout …Run Code Online (Sandbox Code Playgroud) 调用QCoreApplication::hasPendingEvents()或QAbstractEventDispatcher::instance()->hasPendingEvents()在线程内部工作正常.但是,在它之外,后者(具有适当的参数)总是返回false(前者不能在外部使用,因为它指的是从中调用它的线程).
这是一个完整的代码:
#include <QCoreApplication>
#include <QAbstractEventDispatcher>
#include <QThread>
#include <QDebug>
bool hasPendingEvents(QThread *thread = 0) {
return QAbstractEventDispatcher::instance(thread)->hasPendingEvents();
}
class MyObject: public QObject {
Q_OBJECT
public slots:
void Run() {
qDebug() << __LINE__ << hasPendingEvents() << QCoreApplication::hasPendingEvents();
QThread::sleep(1);
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QThread thread;
MyObject t;
t.moveToThread(&thread);
thread.start();
for (int i = 0; i<4; ++i) QMetaObject::invokeMethod(&t, "Run", Qt::QueuedConnection);
for (int i = 0; i<10; ++i) {
QThread::msleep(500); …Run Code Online (Sandbox Code Playgroud) 我创建了一个派生自QAbstractListModel并重新实现所有必要功能的类.我创建了一个对象,将一些初始数据填入模型(所有beginInsertRows等完成),然后将它(对象)传递给qml via setContextProperty.我正在使用QQuickView.一旦qml被show()命令显示,我产生一个QThread我使用Model对象的指针.线程通过直接调用Model的addData(..)函数(具有beginInsertRowsetc)继续向模型添加数据.
问题:没有UI的更新.我在QtCreator的"应用程序输出"窗格中列出了以下内容:
QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'
(Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)
Run Code Online (Sandbox Code Playgroud)
这里的表格显示了完全相同的问题,但我不能使用那里提到的信号和插槽.
编辑:
从主线程运行addData()(使用链接中提到的信号槽但不是子类QThread)确实将ListView更新为初始数据,但是在dataChanged()信号之后视图没有更新.让我更清楚地解释一下.
/*This is the class in which data is stored*/
class ClientCardModel : public QAbstractListModel {
....
QList<ClientCard*> m_list;
};
...
ClientCardModel hand; // object to send to qml
...
// New worker thread created and all the following codes are exexuted in that …Run Code Online (Sandbox Code Playgroud) 使用:C++ (MinGW),Qt4.7.4,Vista (OS),intel core2vPro
我需要以完全相同的方式处理2个巨大的文件.所以我想从2个单独的线程中为2个单独的文件调用处理例程.GUI线程没有什么重要的; 只显示一个标签并运行一个事件循环来检查线程终止条件的发射并相应地退出主应用程序.我预计这会同样地利用两个核心(intel core2),但相反,我从任务管理器看到其中一个核心被高度利用而另一个核心没有(尽管不是每次我都运行代码); 处理2个文件所花费的时间远远超过处理一个文件所花费的时间(我认为它应该相等或稍微多一点,但这几乎等于在非线程中一个接一个地处理2个文件应用).我可以以某种方式强制线程使用我指定的核心吗?
QThread* ptrThread1=new QThread;
QThread* ptrThread2=new QThread;
ProcessTimeConsuming* ptrPTC1=new ProcessTimeConsuming();
ProcessTimeConsuming* ptrPTC2=new ProcessTimeConsuming();
ptrPTC1->moveToThread(ptrThread1);
ptrPTC2->moveToThread(ptrThread2);
//make connections to specify what to do when processing ends, threads terminate etc
//display some label to give an idea that the code is in execution
ptrThread1->start();
ptrThread2->start(); //i want this thread to be executed in the core other than the one used above
ptrQApplication->exec(); //GUI event loop for label display …Run Code Online (Sandbox Code Playgroud) 我正在使用50 fps的摄像头(在Ubuntu环境和Qt框架中),每隔20 ms,我就会得到一个帧来处理.
我写了一个代码来从相机读取图像,然后将它们存储在硬盘中.
while(3.14)
{
cv::Mat Camera_Image = Capture_Image();
double T1 = (double)cv::getTickCount();
cv::imwrite (STORE_ADDRESS,Camera_Image);
T1 = (((double)cv::getTickCount() -T1)*1000)/cv::getTickFrequency();
print(T1);
}
Run Code Online (Sandbox Code Playgroud)
当我看到输出时,对于2048*1080图像尺寸,将单个图像写入硬盘的时间约为30毫秒.每个图像都是单通道(灰度)但我在硬盘中以.jpg格式编写它们.硬盘中每个图像的大小约为500K字节.
由于我在大约20毫秒内捕获一帧,我无法将它们全部写入硬盘实时.我已经使用Qthread编写了我的代码并创建了一个队列来查看是否有任何改进,但结果是相同的,它只是一个内存开销.
是否有可能改变这种情况,或使用其他库将这些图像更快地写入硬盘?如果可以的话,我也更喜欢Qt解决方案......
另外我需要将每一帧写入硬盘,所以请不要使用Motion压缩算法,因为它们不适用于我的情况....
代码:Mainwindow.cpp
Qlist<cv::Mat> FINAL_IM_VEC;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
IMREAD *IMR = new IMREAD(this); // an instance of IMREAD Class which reads camera frames
IMWRITE *IMW = new IMWRITE(this); // an instance of IMWRITE Class which Writes camera frames into hard disk
QThread *IMAGE_READ_Thread = new QThread(this);
QThread *Image_Store_Thread = new QThread(this); …Run Code Online (Sandbox Code Playgroud)