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的主要内容,如果未能解决你的问题,请参考以下文章

从另一个 std::thread 调用 Qt 对象方法

Qt + OpenCV 使用 std::thread 播放视频

正如我所料,Qt GUI 不适用于 std::thread

如何在 Qt 的主事件循环中使用 std::thread?

如何使用 QThread 创建一个分离的线程,就像在 std::thread 中一样

std::thread 中的参数。如何运作?