std::thread 消耗 Qt 中的所有 CPU
Posted
技术标签:
【中文标题】std::thread 消耗 Qt 中的所有 CPU【英文标题】:std::thread consumes all CPUs in Qt 【发布时间】:2014-07-16 09:18:22 【问题描述】:我有一个功能。在我的函数中有一个 c++ 线程和一个 Qtimer。通过 c++ 线程我接收 ARP 回复数据包并通过 QTimer 我发送 ARP 请求数据包。
简化结构:
int foo()
... some codes ...
QTimer::singleShot(1000, this, SLOT(beginSending()));
std::thread tCapture(Capture);
tCapture.join();
return 0;
void Capture()
while ( ! finishCapturing )
do sth
在tCapture
线程中,我有一个消耗所有 CPU 的 while 循环,并且 Qtimer 不起作用!
我使用.join()
,因为我想等待线程完成。
当我在 Qtimer 插槽中设置finishCapturing
标志时,线程将完成。
上面的代码不能正常工作,因为c++线程消耗了所有的CPU!
有什么问题?
非常感谢。 亚阿里。
【问题讨论】:
可能会尝试在此期间进入睡眠状态,以便让处理器执行其他操作。 我也建议使用 .run(),并在执行结束时等待 tCapture 发出的信号。 你怎么知道线程消耗了所有的CPU? 我使用了 Sleep(1000) 但不起作用! "我使用.join()
,因为我想等待线程完成。" - 在您等待时不会发生任何其他事情,因此没有任何事情发生也就不足为奇了。让线程继续运行,并在捕获完成后加入它。
【参考方案1】:
问题是在创建线程后立即加入线程,这阻塞了 GUI 线程和 QTimer
以及该线程上的所有插槽。
您应该做的是在捕获完成后发出signal
;
public void beginSending()
//do sending and capture
finishCapturing =true;
emit finshedCapture();
如果需要,您可以将 while 的主体放在一个插槽中,并使用超时为 0 的 QTimer 重复调用它(这意味着该插槽将被尽可能频繁地调用)。
然后你可以将finshedCapture()
信号连接到QTimer的stop()
槽
int foo()
... some codes ...
QTimer::singleShot(1000, this, SLOT(beginSending()));
QTimer* timer = new QTimer(this);
connect(timer, signal(timeout()), this, slot(Capture()));
connect(this, signal(finshedCapture()), timer, slot(stop()));
connect(this, signal(finshedCapture()), timer, slot(deleteLater()));//cleaup when done
timer->setTimeout(0);
timer->setSingleShot(false);
timer->start();
return 0;
void Capture()
//no while because the timer will call it as needed
//do sth
【讨论】:
感谢您的回复和您的代码。你的代码很有帮助,但正如我在第一篇文章中所说,我不希望 foo 函数在完成 Capture & the slot 之前完成。 那么您应该重新设计调用代码,以便 foo 可以在捕获完成之前返回,并且您可以使用信号和插槽来执行之后的代码 这是一个简化的代码。我必须返回 Capture 的结果,所以我需要在完成 Capture 后完成 foo 函数。 @MohammadRezaRamezani 你可以让finishedCapture
信号在其参数中包含结果
foo 是我班的成员。我想从这个类创建 dll。我需要 foo 函数返回它调用的结果,而不是通过信号和槽。【参考方案2】:
没有看到更多代码,这是猜测:
1:Capture()
不会阻塞,因此会消耗操作系统提供的 CPU 时间 - 在轻负载的多核系统上,这将是一个 CPU 的 100%。
2: foo()
在主线程上被调用。然后它会尝试使用您的线程join()
- 这会阻塞直到线程完成。我没有看到任何设置 finishCapturing
,所以它没有。
3:QTimer
通过 run-loop 调度 - 这是阻塞的。
实际上,这是主线程的死锁。
【讨论】:
我说我需要使用 .join() 并说我在 QTimer 插槽中设置了 finishCapturing 来闪烁线程。我认为这不是僵局! @MohammadRezaRamezani his(1) 是正确的!加Sleep(100);
让cpu做别的事
调用join()
会阻塞计时器操作所依赖的事件循环。线程是在咀嚼每个可用的周期还是在休眠,这无关紧要。以上是关于std::thread 消耗 Qt 中的所有 CPU的主要内容,如果未能解决你的问题,请参考以下文章
Qt + OpenCV 使用 std::thread 播放视频