【问题标题】:std::thread consumes all CPUs in Qtstd::thread 消耗 Qt 中的所有 CPU
【发布时间】: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(),因为我想等待线程完成。" - 在您等待时不会发生任何其他事情,因此没有任何事情发生也就不足为奇了。让线程继续运行,并在捕获完成后加入它。

标签: c++ multithreading qt cpu stdthread


【解决方案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() 会阻塞计时器操作所依赖的事件循环。线程是在咀嚼每个可用的周期还是在休眠,这无关紧要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多