多线程建议

Hic*_*ani 5 c++ qt multithreading opencv

我正在开发一个应用程序,主要目标是从图像采集器中获取图像,进行一些处理,然后在GUI上显示图像.帧抓取器连接到PCIe.我正在使用帧抓取器SDK.图像流非常慢10到100张图像/秒我在这里对我的代码以及如何优化它有一些建议.首先,我从一个继承自Qthread的类中获取run()函数,我抓取一个图像并将其放在缓冲区queuecv :: Mat>上.

void ImageIn::run(){
        _cam->allocMemory();
        _cam->startAquisition();
        _runningThread = true;

        while(_runningThread)
        {
             Mat image(_cam.getSizeX(), _cam.getSizeY(), CV_16U, _cam->getImageDMA0());

             _ctrl->getMutexIn()->lock(); // Lock BufferIn
             _ctrl->getBufferIn()->push(image); // store Image in BufferIn
             _ctrl->getMutexIn()->unlock(); // Unlock bufferIn
        }

}
Run Code Online (Sandbox Code Playgroud)

图像存储在缓冲区中,然后处理线程做一些工作......

void ImageProcessing::run(){
while(_runningThread){
if (_ctrl->getMutexIn()->tryLock()){
    while(!_ctrl->getBufferIn()->empty()){
        _ctrl->getBufferIn()->front().convertTo(tempConvert, CV_32F);
        _bufferLocalIn.push(tempConvert);
        _ctrl->getBufferIn()->pop();
    }
    _ctrl->getMutexIn()->unlock();
}

// Do some processing and put image and a buffer for GUI
}
}
Run Code Online (Sandbox Code Playgroud)

所以,我有一些问题: - 线程1由于阻塞功能而获得图像,因此CPU消耗很低,但线程2连续运行并消耗大量CPU重新评估我可以做些什么来修复它? - 这是编码的正确方法吗?


所以我试过了:

QThread* thread = new QThread;
ImageWriter* worker = new ImageWriter();
worker->moveToThread(thread);

QTimer* timer = new QTimer();
int msec = 100;
timer->setInterval(msec);

QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
QObject::connect(timer, SIGNAL(timeout()), thread, SLOT(start()));
timer->start();
Run Code Online (Sandbox Code Playgroud)

好吗?

The*_*ght 2

由于Qt是一个事件驱动的框架,每个线程都有一个事件队列,用于接收事件并将它们发送到各个对象来接收它们。

如果线程中的任何代码部分本质上有一个 while(1) 循环,则事件传播不会发生,这就是您在两个线程中所做的事情

while(_runningThread)
Run Code Online (Sandbox Code Playgroud)

无限循环中的事件处理不足是 CPU 消耗过多的原因。

可以通过在无限循环中调用QApplication::processEvents来让 Qt 处理事件,但这并不理想。

更好的方法是使用QTimer对处理进行时间切片,并允许事件传播自然发生。这需要在保存处理状态然后返回到事件循环之前确定处理可以发生多长时间。计时器的滴答声将调用您的处理函数,然后该函数可以恢复状态并继续。

如果您创建一个从 QObject 派生的处理类并将其移至 QThread,而不是直接从 QThread 本身继承,则此方法会更容易。有一篇关于如何真正使用 QThread 的精彩文章,可以用作如何执行此操作的模板。

最后,考虑一下您可以有多个QThread,也可以QObject在一个 上运行多个QThread。一般来说,如果线程数超过可用处理器核心数,您将不会受益。

如果您知道目标机器是四核,则可以创建3个额外的QThread(总共4个,包括主线程),创建多个处理对象并将它们移动到不同的线程以提供最佳处理。