标签: qthread

QThreads,QObject和睡眠功能

我遇到的问题是,我QThreads根据大量文章决定实施他们应该采用的方式:
http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

并且问题在于,因为算法是在单独的QObject(包装QThread)中运行的.我该怎么称呼Thread::Sleep或者说什么呢?任何想法?

该软件的一个小描述.基本上我的申请解决了TSP(旅行商问题).随着搜索的进行,它将历史中的所有状态保存为frames...(如可视框架).搜索算法将在一个线程上运行.主线程正在使用GUI进行处理.然后有Mediaplayer类似的线程告诉Main线程在屏幕上显示什么帧.那么睡眠在哪里?在gui中有一个滑块,用户可以使用它来快进或以正常速度前进.滑块通过信号槽告诉Mediaplayer线程更快或更慢.

c++ qt qthread

8
推荐指数
1
解决办法
1万
查看次数

用Qt进行简单的多线程处理:我这样做了吗?

我是StackOverflow的新手,想知道我是否正确行事:

我正在编写一个简单的Qt应用程序来测试多线程(我也是一个全新的东西).我创建了一个包含小部件的MainWindow,以及一个继承QThread并覆盖run()方法的类MyThread.

应用程序只显示两个按钮,"启动计数器"和"停止计数器",以及一个文本字段.当按下"启动计数器"时,创建工作线程并在后台运行,在while循环中连续递增计数器并用更新的值发信号通知主线程(GUI所在的位置).按下"停止计数器"时,会向主线程发送一个停止while循环的信号,计数器停止,直到再次按下"启动计数器".

这非常好用......但这是最好的方法吗?我是新手,并阅读了很多人说"不要继承QThread"和其他人说"子类QThread",这有点令人困惑.如果这不是实现这种事情的最佳方式(在后台线程中使用"start"和"stop"按钮运行计算密集型循环),那是什么?如果我做错了,我该怎么做呢?我不想学习错误的方法.

谢谢!这是代码:

MyThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
   Q_OBJECT

public slots:
    void stopRunning();

protected:
   virtual void run();

signals:
   void signalValueUpdated(QString);

private:
    bool isRunning;

};
Run Code Online (Sandbox Code Playgroud)

MyThread.cpp

#include "MyThread.h"
#include <QString>

void MyThread::run()
{
    qDebug("Thread id inside run %d",(int)QThread::currentThreadId());

    static int value=0; //If this is not static, then it is reset to 0 every time this function is called.
    isRunning = 1;
    while(isRunning == 1)
    {
        QString string = QString("value: …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading qt4 qthread

8
推荐指数
1
解决办法
2万
查看次数

带有Qt 5.1的共享QGLWidgets问题的螺纹OpenGL

我使用两个QGLWidgets.一个用于加载纹理,一个用于渲染,但它不起作用.

我在http://blog.qt.digia.com/blog/2011/06/03/threaded-opengl-in-4-8/上使用了以下说明

纹理上传线程上传许多(或大)纹理通常是一项昂贵的操作,因为数据量被推送到GPU.同样,这是可能不必要地阻止主线程的那些操作之一.在4.8中,您可以通过创建一对共享QGLWidgets来解决此问题.其中一个小部件在一个单独的线程中是最新的,但从未在屏幕上显示.主线程通知上传线程要上传哪些图像,上传线程只是在每个图像上调用bindTexture(),然后在每个图像完成时通知主线程,以便可以将其绘制到屏幕上.

使用Qt 4.8和MinGW它工作正常,但现在我使用Qt 5.1和MSVC.当我想让线程中的小部件变为当前时,我收到错误:

无法使QOpenGLContext在另一个线程中保持最新状态

我理解错误,但我该如何解决它.当我没有设置小部件当前我无法加载纹理(在bindTexture()函数冻结).我也想知道,为什么它适用于我的旧QT版本.当出现错误时,我可以按"忽略错误",程序无论如何都会加载纹理.

以下是一些示例代码:

加载纹理:

GLContext::GLContext(QWidget *parent, QGLWidget *myDisplayWidget) :
  QGLWidget(parent,myDisplayWidget)
{
}
Run Code Online (Sandbox Code Playgroud)

...

GLContext* myTextureWidget = new GLContext(this,myDisplayWidget);
Run Code Online (Sandbox Code Playgroud)

...

void TextureLoadingThread::run()
{    
    makeCurrent(); //Here is the bug!
    QImage *im = new QImage(filename);
    GLuint textid = myTextureWidget->bindTexture(*im, GL_TEXTURE_2D, GL_RGBA);
}
Run Code Online (Sandbox Code Playgroud)

编辑:

当我将myTextureWidget的上下文移动到它运行的线程时,但是当GUI将构建时,我从API获得makeCurrent Error(堆栈跟踪在QT5Widgetsd中的QLineEdit :: setPlaceHolderText函数中说明).当我在主窗口显示几秒后将myTextureWidget移动到线程时,一切正常.但是我怎么知道什么时候qt完成了所有GUI构建的东西?我使用QGLWidget视口将GUI绘制到QGraphicsView.

myTextureWidget->context()->moveToThread(myTextureLoadingThread);
Run Code Online (Sandbox Code Playgroud)

c++ qt qtgui qthread qtcore

8
推荐指数
1
解决办法
6724
查看次数

QThread:在线程仍在运行时被销毁?

QThread当我按下按钮Run时,我想启动我.但编译器输出以下错误:

QThread: Destroyed while thread is still running
ASSERT failure in QThread::setTerminationEnabled(): "Current thread was not started with QThread.", file thread\qthread_win.cp.
Run Code Online (Sandbox Code Playgroud)

我不知道我的代码有什么问题.

任何帮助,将不胜感激.

这是我的代码:

SamplingThread::SamplingThread( QObject *parent):
   QwtSamplingThread( parent ),
   d_frequency( 5.0 )
{
   init();
}

MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{.......
  .....
   run= new QPushButton ("Run",this);
   stop= new QPushButton("Stop",this);
   connect(run, SIGNAL(clicked()),this, SLOT (start()));
}

MainWindow::start
{
   SamplingThread samplingThread;
   samplingThread.setFrequency( frequency() );
   samplingThread.start();
}

int main( int argc, char **argv )
{
   QApplication app( argc, …
Run Code Online (Sandbox Code Playgroud)

c++ qt signals-slots qthread qwt

8
推荐指数
2
解决办法
3万
查看次数

Qt:qthread在关闭期间线程仍在运行时被破坏

我有一节课:

class centralDataPool : public QObject
{
    Q_OBJECT
public:
    centralDataPool(QObject * parent = 0);
    ~centralDataPool();
    commMonitor commOverWatch;

private:
    QThread monitorThread;
    int totalNum;

signals:
    void createMonitor(int);
};
Run Code Online (Sandbox Code Playgroud)

在它的构造函数中我做了:

centralDataPool::centralDataPool(QObject* parent) : QObject(parent),totalNum(0)
{
    connect(this, SIGNAL(createMonitor(int)), &commOverWatch, SLOT(createMonitor(int)));
    commOverWatch.moveToThread(&monitorThread);
    monitorThread.start();
}
Run Code Online (Sandbox Code Playgroud)

当我调用此类的析构函数时,我收到错误消息:

qthread destroyed while thread is still running
Run Code Online (Sandbox Code Playgroud)

但是当我试图在类centralDataPool的析构函数中终止monitorThread时,

centralDataPool::~centralDataPool()
{
    monitorThread.terminate();
}
Run Code Online (Sandbox Code Playgroud)

我得到内存泄漏.

在销毁其所有者对象期间终止线程的正确方法是什么?

c++ qt multithreading qthread

8
推荐指数
1
解决办法
8045
查看次数

如何使用QWaitCondition实现一个永远运行的QThread但仍然需要在执行此操作时捕获另一个Slot

我实现了一个类,它可以通过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)

c++ qt boost-asio qthread

7
推荐指数
1
解决办法
3042
查看次数

完成()连接到QObject的deletelater的QThread

在这里提出这个问题之前,我已经想了很多并阅读了很多文章.这些文章都没有给我一个正确的答案.

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明确指出,在发出信号时调用插槽的顺序是不确定的

上面提到的文章链接中有很多评论.即便是作者也无法完全回答这个问题

signals quit qthread qobject

7
推荐指数
1
解决办法
9082
查看次数

使主线程等到所有其他Qthread完成

有没有办法强制主线程等到从它创建的所有线程完成他们的工作,然后才能完成程序.我的意思是:

int main(){
    QthreadClass a; // in cons' a thread is created and running
    QthreadClass b; // same as before

    *** wish to wait till both created thread finished their jobs ***

    return 0;
Run Code Online (Sandbox Code Playgroud)

}

c++ qthread

7
推荐指数
2
解决办法
2万
查看次数

Qt Main-Gui和其他线程+事件循环

我正在尝试理解Qt的整个内部过程以及当我使用不同的线程时它是如何工作的.

正如我所理解的(谷歌搜索和探索Qt源代码),如下:

  • 每个线程都有一个本地"挂起事件列表"和一个exec与该列表交互的本地事件循环(如果我调用).
  • QCoreApplication::postEvent(obj, e)将该对添加到(obj, e)obj线程的"待处理事件列表"中.
  • 每个线程都有一个本地"事件调度程序"(QAbstractEventDispatcherspecializations),其目的是读取系统事件.因此,对于不同的平台,它存在a QEventDispatchWin,a QEventDispatchUnix,a QEventDispatchSymbian等.对于gui事件,Qt也有QEventDispatchX11(继承自QEventDispatchUnix),S60(来自Symbian)等.

考虑到所有这些,exec呼叫的工作原理如下:

Thread's `exec`:
 ? create a QEventLoop object.
 ? call QEventLoop.exec()
   ? call repeatedly eventDispatcher's processEvents with WaitForMoreEvents flag.
     ? call to QCoreApplication::sendPostedEvents
     ? while (!pending system events)
     ?  ? read system event
     ?  ? create an appropiate QEvent e and detect its target QObject o. …
Run Code Online (Sandbox Code Playgroud)

qt qt4 event-handling qthread

7
推荐指数
1
解决办法
4495
查看次数

由于另一个QThread,QApplication线程冻结

在我的Qt应用程序中,我创建了一个QThread应该定期执行一些繁重的计算任务.主QApplication线程应该维护GUI(不包括在示例中)并执行一些定期更新.两个线程都有自己的定时器来启用常规update()调用.

问题:当工作线程的计算工作负载超过某个临界值时,我的主线程停止接收计时器事件.

示例代码如下.当主线程调用update()时,它输出"Main",工作线程调用"Worker".如果你运行它,你会看到"工人"定期打印,"主"正好出现两次(一个在开头,一个在约5秒).在全功能GUI应用程序的情况下,这实际上意味着完全GUI冻结.

一些观察.

  1. 通过对内循环(而不是1000)设置100限制来减少工作量将解决问题(两个update()方法都将定期调用).
  2. 将工作线程定时器信号的连接类型设置为Qt :: DirectConnection将解决问题.

所以,你可以看到我有几个解决方法,但我很感激任何人解释我的原始代码有什么问题.我希望线程能够独立地执行它们的事件循环.我知道我通过一个很长的update()操作来阻止工作线程事件循环,但为什么它在世界上会影响主线程呢?

PS是的,我知道QConcurrent替代方案.但我只是想明白.

TEST.CPP

#include <windows.h>
#include <QApplication>

#include "test.h"

HANDLE mainThread_ = INVALID_HANDLE_VALUE;
QApplication *app_ = 0;
MyObj *obj_ = 0;
MyThread *thread_ = 0;

MyObj::MyObj()
    : timer_(0)
{
    timer_ = new QTimer(0);
    connect(timer_, SIGNAL(timeout()), this, SLOT(update()));
    timer_->start(10);
}

void MyObj::update()
{
    printf("Main\n");
}

void MyThread::run()
{
    timer_ = new QTimer(0);
    connect(timer_, SIGNAL(timeout()), this, SLOT(update()));
    timer_->start(10);

    exec();
}

void MyThread::update()
{
    printf("Worker\n");

    // do some …
Run Code Online (Sandbox Code Playgroud)

qt multithreading qthread qtcore

7
推荐指数
1
解决办法
1292
查看次数