Multithreading QT->;如果线程正在消耗所有资源并且不允许执行插槽,如何终止线程
我正在开发Qt5.5,并创建了一个使用第三方库API的独立线程。此Api函数在执行时会消耗所有资源,不允许在该线程中执行任何其他函数 这个新线程以点击按钮开始,比如说“开始”,当我按下停止按钮时,我不知道如何停止或终止线程。下面是我的示例Multithreading QT->;如果线程正在消耗所有资源并且不允许执行插槽,如何终止线程,multithreading,qt,qthread,Multithreading,Qt,Qthread,我正在开发Qt5.5,并创建了一个使用第三方库API的独立线程。此Api函数在执行时会消耗所有资源,不允许在该线程中执行任何其他函数 这个新线程以点击按钮开始,比如说“开始”,当我按下停止按钮时,我不知道如何停止或终止线程。下面是我的示例 threadWorking = new QThread(); workHeavy = new WorkingHard; workHeavy->moveToThread( threadWorking ); co
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。如果我使用terminate(),我还需要像我在Fifunction slotStopStream中指出的那样释放内存吗
请建议我根据id或其他信息终止线程
你不需要这样的建议。终止正在运行的线程会泄漏资源,并可能使进程处于损坏状态,例如,堆管理器的数据结构可能已损坏,或者其他全局状态可能已损坏不要强制终止线程-其他任何行为都是未定义的行为
我非常怀疑g\u main\u loop\u run
是否“消耗”了所有资源。嗯,它正在忙着做某事,或者在等待事情的发生。毕竟,这是一个事件循环。:)调用g\u main\u loop\u run
与在QEventLoop
上调用exec()
没有太大区别
您可以调用g\u main\u loop\u quit
退出事件循环。如果它是QEventLoop
,您可以从任何线程对其调用quit
。但是我不确定g\u main\u loop\u quit
是否是线程安全的,文档对此没有说明。唉,我们不必担心这一点:我们可以从工作线程本身调用它
我们将在循环的上下文中调用g\u main\u loop\u 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
请建议我根据id或其他信息终止线程
你不需要这样的建议。终止正在运行的线程会泄漏资源,并可能使进程处于损坏状态,例如,堆管理器的数据结构可能已损坏,或者其他全局状态可能已损坏不要强制终止线程-其他任何行为都是未定义的行为
我非常怀疑g\u main\u loop\u run
是否“消耗”了所有资源。嗯,它正在忙着做某事,或者在等待事情的发生。毕竟,这是一个事件循环。:)调用g\u main\u loop\u run
与在QEventLoop
上调用exec()
没有太大区别
您可以调用g\u main\u loop\u quit
退出事件循环。如果它是QEventLoop
,您可以从任何线程对其调用quit
。但是我不确定g\u main\u loop\u quit
是否是线程安全的,文档对此没有说明。唉,我们不必担心这一点:我们可以从工作线程本身调用它
我们将在循环的上下文中调用g\u main\u loop\u 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。您的示例远远不够完整,也远远没有达到最低要求。也就是说,研究一下“线程取消”这个术语,以及为什么它会有问题。使用不同的流程可能是另一种选择。您应该显示您的工作循环。这就是你应该把线程终止检测放在那里的地方,但是如果不知道你有什么样的代码,你很难给出建议。如果我使用terminate(),我还需要像我在函数slotStopStream中指出的那样释放内存吗?当然,如果您可以通过释放资源使内存更干净,那么您应该这样做。@samprat Thread terminate在那里结束线程,然后可能使例如数据结构处于无效状态。如果你真的没有其他方法告诉线程以可接受的延迟停止,那么只能将其作为最后的手段使用。你的示例远远没有按照要求完成和最小化。也就是说,研究一下“线程取消”这个术语,以及为什么它会有问题。使用不同的流程可能是另一种选择。您应该显示您的工作循环。这就是你应该把线程终止检测放在那里的地方,但是如果不知道你有什么样的代码,你很难给出建议。如果我使用terminate(),我还需要像我在函数slotStopStream中指出的那样释放内存吗?当然,如果您可以通过释放资源使内存更干净,那么您应该这样做。@samprat Thread terminate在那里结束线程,然后可能使例如数据结构处于无效状态。如果你真的没有其他方法告诉线程以可接受的延迟停止,那么只能将其作为最后手段。非常感谢,伙计。我会试试,让你们知道我试过了,我发现当从不同的线程调用时,它会进入quitLoop,但视频不会stop@sampratquitLoop
是否返回?我在lambda函数之后添加了调试stmt,并成功打印了它。非常感谢