gpt4 book ai didi

c++ - Qt - 同步线程不工作 - 线程停止但实际上没有停止,有时在不应该的时候停止

转载 作者:行者123 更新时间:2023-11-28 00:15:12 24 4
gpt4 key购买 nike

我有四个线程。两种使用OpenCV播放和分析视频,一种保存数据并充当视频和GUI之间的中间人,一种是GUI。

我的想法是这样的 - 视频线程做事,将帧发送给中间人,然后自行停止。如果它是发送的帧对中的第一帧,中间人什么都不做,只设置一个标志 - otherFrame。理论上,由于一个视频停止了,现在另一个视频发送一个帧,另一个帧的标志为 True,所以中间人将两个帧发送到 onPassFramesGui,帧被放置在 QLabels 中,然后两个线程都恢复。然后循环。

这就是理论,我毫不怀疑它是错误的。实际上,分辨率较低的视频迟早会超过另一个视频。仿佛从未停歇。

在视频线程中,虽然它们做的事情略有不同,但这是代码的共同部分:

for(nrKlatkiOne=1; nrKlatkiOne<maxFramesOne; nrKlatkiOne++) {
(....)
emit sendFrameOne(imageOne, nrKlatkiOne);
pauseThread();
pause.lock(); //mutex
if(threadPausedOne==true){
pausedCond.wait(&pause); //QWaitCondition
}
pause.unlock();
}

void VideoOne::pauseThread() { //in VideoTwo "One"s are replaced with "Two"s, so the variables are exclusive to their threads
if(threadPausedOne==false){
pause.lock();
threadPausedOne=true;
pause.unlock();
}
}

void VideoOne::resumeThread() {
if(threadPausedOne==true){
pause.lock();
threadPausedOne=false;
pause.unlock();
pausedCond.wakeAll();
}
}

在中间线程中,这是接收信号的插槽(VideoTwo 有类似的信号):

void Analiza::onSendFrameOne(QImage frameOneImage, int frameNoOne) {  

//videoOne->pauseThread();
one = frameOneImage;
frOne = frameNoOne;

if(otherFrameTwo == true && videoTwoLoaded == true){
emit passFramesGui(one, two, frOne, frTwo);
pauseMutex.lock();
otherFrameOne = false;
otherFrameTwo = false;
pauseMutex.unlock();
} else if(videoTwoLoaded == false) {
emit passFramesGui(one, two, frOne, frTwo); //to GUI
}
if(otherFrameTwo == false){
pauseMutex.lock();
otherFrameOne = true;
pauseMutex.unlock();
qDebug() << "otherFrameOne = true";
}
}

最后但同样重要的是,请耐心等待,此函数在 GUI 中设置图像

void MainWindow::onPassFramesGui(QImage one, QImage two, int frameNoOne, int frameNoTwo){ 

if(videoOneLoaded==true) {
<converting image>
<keeping aspect ratio>
(setting stuff)
}

if(videoTwoLoaded==true) {
<same stuff here>
}

if(videoOneLoaded == true) {
videoOne->resumeThread();
}

if(videoTwoLoaded == true) {
videoTwo->resumeThread();
}
}

我已经放置了 QDebug 消息来大致了解发生了什么。迟早会发生这种情况:

(....)
otherFrameOne == true && videoOneLoaded == true //frames emitted from onSendFramesTwo
otherFrameTwo = true //onSendFramesTwo received the frame, waits
otherFrameTwo == true && videoTwoLoaded == true //onSendrameOne sent the frames
otherFrameOne = true //onSendFrameOne received a frame
otherFrameOne = true //onSendFrameOne received another frame? But it's stopped...

我很确定停止线程有效。如果我从其中一个中删除 resumeThread() ,程序就会停止。它将发送帧 1、2 -> gui,然后发送 1,然后它就会停止。

另一种情况是只加载了一个视频,而不是两个。视频线程将随机停止而不是恢复。我有一个 qDebugs 消息的信号,在视频停止后,它不会做任何事情(当我更改标签时可以恢复 - 这会导致 threadPausedOne/Two设置为 true,然后设置为 false。

代码编译时没有任何错误或警告。

正确的做法是什么?这是我第一次做这种事。

哦,一个额外的问题。拥有两个略有不同的独立对象更好,还是拥有一个多 60% 的代码并只创建多个实例更好?

最佳答案

你把它复杂化了,引入了很多标志和同步对象。我建议您为每个视频线程使用两个 QSemaphore。我将它们命名为 allowWorkhasFrame

视频线程将按如下方式工作:

// Wait until middleman allows work (when it has handled a pair of frames)
allowWork.acquire(1);

// Do frame processing here
// ...

// Tell middleman one frame is ready
hasFrame.release(1);

中间人线程将按如下方式工作:

// Wait until both video threads have a frame
video1.hasFrame.acquire(1);
video2.hasFrame.acquire(1);

// Handle a pair of frames here
// ...

// Tell video threads to make another pair of frames
video1.allowWork.release(1);
video2.allowWork.release(1);

在启动代码中,您会将allowWork初始化为1,将hasFrame初始化为0。

使用这种方法,也可以很容易地为来自 video1 和 video2 的帧添加缓冲区(例如,两个视频线程都会工作,直到它们各自准备好 16 帧,而中间人仍然会在一对可用时处理),这样您可能会获得更好的线程利用率。

关于c++ - Qt - 同步线程不工作 - 线程停止但实际上没有停止,有时在不应该的时候停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30773530/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com