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,但视频没有停止 @sampratquitLoop
是否返回?
我在 lambda 函数后添加了 debug stmt,打印成功。以上是关于QT - >如果线程正在消耗所有资源并且不允许插槽执行,如何杀死线程的主要内容,如果未能解决你的问题,请参考以下文章