QT - >如果线程正在消耗所有资源并且不允许插槽执行,如何杀死线程

Posted

技术标签:

【中文标题】QT - >如果线程正在消耗所有资源并且不允许插槽执行,如何杀死线程【英文标题】:QT -> how to kill thread if thread is consuming all resources and doesnt allow slot to execute 【发布时间】:2016-02-02 23:57:41 【问题描述】:

我正在开发 Qt 5.5,并创建了一个使用 3rd 方库 API 的单独线程。这个 Api 函数在执行时会消耗所有资源,并且不允许任何其他函数在该线程中执行。

这个新线程以单击“开始”按钮开始,当我按下停止按钮时,我只是不知道如何停止或终止线程。下面是我的示例

threadWorking = new QThread();
 workHeavy    = new WorkingHard; 

        workHeavy->moveToThread( threadWorking );

        connect( threadWorking, SIGNAL( started() ),        workHeavy,     SLOT( slotStartStream() ) );
        connect( workHeavy,     SIGNAL( sigStopStream() ),  threadWorking, SLOT( quit() ) );
        connect( workHeavy,     SIGNAL( sigStopStream() ),  workHeavy,     SLOT(deleteLater() ) );
        connect( threadWorking, SIGNAL( finished() ),       threadWorking, SLOT(deleteLater() ) );

        connect( workHeavy,     SIGNAL( sigStartStream() ), this, SLOT( slotTrueStreamRun()  ) );
        connect( workHeavy,     SIGNAL( sigStopStream() ),  this, SLOT( slotFalseStreamRun() ) );

        connect( this,            SIGNAL( sigMopsCamStopCmd() ), workHeavy, SLOT(slotStopStream() ) );
        threadWorking->start();

Also// void WorkingHard::slotStartStream() 

    g_main_loop_run( gloop ); // this consumes all resources.

void WorkingHard::slotStopStream() 

  // clean up mess
g_main_loop_quit( gloop );
    gst_element_set_state (pipeline, GST_STATE_NULL);
   // g_main_loop_quit( gloop );
    releaseMemory();

请建议我根据 id 或其他内容杀死线程。有一点很清楚,当函数运行时我不能进入线程。

正如人们建议使用终止。如果我使用 terminate() 是否还需要像我在函数 slotStopStream 中指出的那样释放内存??

【问题讨论】:

您的示例远非完整和最小,如要求。也就是说,研究术语“线程取消”以及为什么会有问题。使用不同的流程可能是一种替代方法。 你应该展示你的WorkingHard工作循环。这就是你应该放置线程终止检测的地方,但是如果不知道你在那里有什么样的代码,就很难给出建议。 正如人们建议的终止。如果我使用 terminate() 是否还需要像我在函数 slotStopStream 中指出的那样释放内存?? 当然,如果你可以通过释放资源让它更干净,你应该这样做。 @samprat Thread terminate 在那里结束线程,然后可能使数据结构处于无效状态。如果您确实没有其他方法可以告诉线程以可接受的延迟停止,请仅将其用作最后的手段。 【参考方案1】:

请建议我根据 id 或其他内容杀死线程。

你不想要这样的建议。终止正在运行的线程会泄漏资源,并且很可能会使您的进程处于损坏状态 - 例如堆管理器的数据结构可能已损坏,或者其他全局状态可能已损坏。 不要强行终止线程 - 其他任何事情都是未定义的行为。

我非常怀疑g_main_loop_run 正在“消耗”所有资源。嗯,它正忙着做某事,或者正在等待事情发生。毕竟,这是一个事件循环。 It's even documented :) 调用 g_main_loop_run 与在 QEventLoop 上调用 exec() 没有太大区别。

您可以致电g_main_loop_quit 退出事件循环。如果它是QEventLoop,您可以从任何线程调用quit。但我不确定g_main_loop_quit 是否是线程安全的,文档对此一无所知。唉,我们不必担心这一点:我们可以从工作线程本身调用它。

我们将从循环的上下文中调用g_main_loop_quit。 lambda 的主体将在工作线程中运行并导致循环退出:

class WorkingHard : public QObject 
   Q_OBJECT
   GMainLoop * gloop;
   ....
;

/// This method is thread-safe
void WorkingHard::quitLoop() 
  auto context = g_main_loop_get_context(gloop);
  g_main_context_invoke(context, +[](gpointer ptr) -> gboolean 
    g_main_loop_quit((GMainLoop*)ptr);
    return FALSE;
  ), (gpointer)gloop);

应用于 lambda 的 + 运算符将其转换为函数指针。它使您不必定义一个独立的函数。

要结束循环,请从任何线程调用quitLoop

请注意,如果您使用的是 Linux,那么 QEventLoop 是基于 glib 事件循环的,您可以直接使用 QEventLoop,而不是使用 GLib api。

【讨论】:

非常感谢伙计。我会试试的,让你们知道 我试过了,我发现当从不同线程调用时它进入了quitLoop,但视频没有停止 @samprat quitLoop 是否返回? 我在 lambda 函数后添加了 debug stmt,打印成功。

以上是关于QT - >如果线程正在消耗所有资源并且不允许插槽执行,如何杀死线程的主要内容,如果未能解决你的问题,请参考以下文章

std::thread 消耗 Qt 中的所有 CPU

Java多线程学习之线程池详解

线程池

线程池是如何重复利用空闲线程的?

JUC--线程池实现

第九章 Java中线程池