• 2088阅读
  • 10回复

[提问]Qt多线程数据处理 [复制链接]

上一主题 下一主题
离线curiosity
 

只看楼主 倒序阅读 楼主  发表于: 01-15
回复本帖可获得1RMB金钱奖励!
每人最多可获奖1次,奖池剩余10RMB金钱 (中奖几率10%)
是这样的,我想借助Qt做一个数据融合的任务,初步想法是这样的,除了GUI线程,还有三个子线程,一个是毫米波雷达数据接收线程(用UDP通信),一个相机图像获取线程,一个对这两个传感器数据进行融合处理的融合线程。
我想要实现在界面上依次点击打开毫米波接收线程和相机图像线程,这个时候两个传感器就开始不断读数了,然后点击融合,开始融合线程。
现在的问题在于,融合线程必须要用到毫米波线程和相机线程的数据,如果采用信号槽的方式不断将毫米波线程和相机线程的数据发给融合线程,如何设置判断条件使得融合线程确实已经完整收到毫米波线程和相机线程的数据了?
另外,我的融合线程处理量比较大,运行比较慢,而两个传感器读数频率比较快,如果用信号槽,不断发送信号给融合线程,融合线程还没处理完,那信号是会阻塞的吗?如果阻塞的话,那融合线程再处理的话就是被阻塞的那一次的数据了,但我想要时刻处理最新的数据,应该如何实现?

如果不用信号槽的话,用QMutex同步的手段是不是可以满足我的功能?
初用Qt多线程,问题比较多,多谢大家了!
管它真理无穷,进一寸有一寸的欢喜!
离线firebolt

只看该作者 1楼 发表于: 01-15
你这个应该采用“生产/消费”模型,数据采集线程把采集到的数据放到一个队列里,融合线程从队列中读取数据并处理。队列需要一个或两个条件变量(队列满,队列空),如果队列满,阻塞采集线程,如果队列空阻塞融合线程。数据量大用线程消息不合适。
1条评分金钱+1
misgn 金钱 +1 - 02-21
离线curiosity

只看该作者 2楼 发表于: 01-15
回 firebolt 的帖子
firebolt:你这个应该采用“生产/消费”模型,数据采集线程把采集到的数据放到一个队列里,融合线程从队列中读取数据并处理。队列需要一个或两个条件变量(队列满,队列空),如果队列满,阻塞采集线程,如果队列空阻塞融合线程。数据量大用线程消息不合适。 (2017-01-15 18:09) 

我之前也想到过用“生产者/消费者”模式,好像要用QWaitCondition来处理是吗?主要是不太熟悉这种用法,看了Qt官方的例子和解释文档之后也是挺懵的。
那如果把采集线程的数据放到一个队列里,队列是用一个数组来存储吗?那这个数组的长度应该多少合适,那我的两个采集线程——毫米波接收线程和相机线程都把数据缓存在各自的队列里是吗?那我的融合线程从这两个队列里取数如何能保证最好能取到最新的数据,因为队列好像是先进先出的吧?
多谢!
管它真理无穷,进一寸有一寸的欢喜!
离线firebolt

只看该作者 3楼 发表于: 01-15
回 curiosity 的帖子
curiosity:我之前也想到过用“生产者/消费者”模式,好像要用QWaitCondition来处理是吗?主要是不太熟悉这种用法,看了Qt官方的例子和解释文档之后也是挺懵的。
那如果把采集线程的数据放到一个队列里,队列是用一个数组来存储吗?那这个数组的长度应该多少合适,那我的两个采集线程——毫 .. (2017-01-15 19:22) 

1、Qt本身就有队列模板QQueue,不过你需要对它在封装一下,加入条件变量。
2、如果你对数据顺序不敏感那就不需要队列了,你只需要保存一个最新的副本就行了,还是加入一个条件变量,有新的数据就通知融合线程处理。
离线firebolt

只看该作者 4楼 发表于: 01-15
我现在做的项目和你这个差不多,我采集线程把DDC信号做FFT后,发送给一个dispatch线程根据设定频率分割给不同的子窗口做显示。我的做法是在dispatch线程里保存一个最新的副本,run函数wait一个条件变量,如果副本发生变化,我就做处理,否则就等待。程序结构大概是这样的。

class TDispatchThread : public QThread
{
public:
       void Start();
       void Stop();
       void dispatch( float *fft, uint32_t length );

protected:
    void waitForChange();
    void run();
   //关闭标志

    bool m_close;
   //fft 锁
    QMutex m_lock;
   // 条件变量
    QWaitCondition m_wait;
    float  *m_FFT_Buffer; //buffer used by IF spectrum FFT
    bool m_Changed;
};
后面简单的写一下处理过程
// ddc 采集线程调用该方法
void TDispatchThread::dispatch(float * fft , uint32_t length )
{
    m_lock.lock();
   memcpy(m_FFT_Buffer,fft,length * sizeof(float));
  ....其它一些操作

   m_Changed = true;
   //通知所有等待的条件变量

    m_wait.wakeAll();   m_lock.unlock();
}
//等待更新信号
void TDispatchThread::waitForChange()
{

    m_lock.lock();
    while(!m_Changed)
        m_wait.wait(&m_lock);
    m_lock.unlock();
}
//线程处理过程
void TDispatchThread::run()
{
     while(!m_close)
    {
       //等待新数据
        waitForChange();
        m_lock.lock();
        //加入数据处理过程
       m_Changed = false;
        m_lock.unlock();
    }
}

大概就这样,ddc采集线程包含dispatch线程,ddc信号fft后调用dispatch方法把数据传给dispatch线程。
dispatch线程有一个QMutex 锁,用来保护fft_buffer,条件变量用来等待新的数据。关闭线程的时候需要
wait一下,等待线程结束。就这样吧。
2条评分好评度+1金钱+1
curiosity 好评度 +1 解释的很详细,我先按照你的方法试一下看看,多谢了! 01-15
curiosity 金钱 +1 解释的很详细,我先按照你的方法试一下看看,多谢了! 01-15
离线curiosity

只看该作者 5楼 发表于: 01-16
回 firebolt 的帖子
firebolt:我现在做的项目和你这个差不多,我采集线程把DDC信号做FFT后,发送给一个dispatch线程根据设定频率分割给不同的子窗口做显示。我的做法是在dispatch线程里保存一个最新的副本,run函数wait一个条件变量,如果副本发生变化,我就做处理,否则就等待。程序结构大概是这样的。
class .. (2017-01-15 20:33) 

你好,关于你这个程序我有几个问题想细问一下:
1、你是在DDC采集线程中将TDispacthThread线程类声明一个对象,然后调用该对象的dispatch函数来给m_FFT_Buffer赋值是吧,那这个TDispacthThread线程的开始也是在DDC线程中调用start()函数吗?TDispacthThread线程开始后运行run()函数,等待条件变量,等待到条件变量之后运行数据处理,锁定互斥量m_lock,那这个时候void TDispatchThread::dispatch(float * fft , uint32_t length )函数由于互斥量的作用会被阻塞是吗?那接收线程还在接收数据吗?如果还在接收并不断调用这个函数,那下次数据处理线程释放m_lock时,得到的fft是阻塞前的旧的值吗?
2、我现在是有两个数据接收线程,那我是要在接收线程类里定义两个互斥量、两个条件变量来实现我得到两个线程的数据之后,才开始数据处理的要求吗?
多谢回答了!
管它真理无穷,进一寸有一寸的欢喜!
离线firebolt

只看该作者 6楼 发表于: 01-16
1、互斥是肯定会发生的,但是我的采集线程不会阻塞,我有个缓冲队列。你如果不想阻塞采集线程
     可以判断一下上一次数据是否处理结束了,如果没有就直接返回。
2、你可以用两个互斥锁给两个不同的数据用,条件变量可以用一个,看哪个数据比较关键就给哪个数据用。

3、我再推荐一个demo给你,Qt 的例子里有个 spectrum的程序,它采集音频做fft,你看看它的处理过程,也许会有帮助。
离线curiosity

只看该作者 7楼 发表于: 01-17
回 firebolt 的帖子
firebolt:1、互斥是肯定会发生的,但是我的采集线程不会阻塞,我有个缓冲队列。你如果不想阻塞采集线程
     可以判断一下上一次数据是否处理结束了,如果没有就直接返回。
2、你可以用两个互斥锁给两个不同的数据用,条件变量可以用一个,看哪个数据比较关键就给哪个 .. (2017-01-16 11:38) 

好的,十分感谢
管它真理无穷,进一寸有一寸的欢喜!
离线a121171026

只看该作者 8楼 发表于: 02-21
多线程是死循环是信号槽触发的吗
离线心竹园长

只看该作者 9楼 发表于: 05-02
有帮助,学习~
离线沉舟破浪

只看该作者 10楼 发表于: 07-12
快速回复
限100 字节
 
上一个 下一个