我正在扩展一个GTK应用程序,该应用程序执行一组占用高CPU负载的操作。我希望通过单击GUI中的按钮来包含停止此操作的可能性。 问题是,正如预期的那样,来自按钮的信号实际上是在操作完成后触发的。
目前,代码有点像这样:
[...]
// code snippet to show the dialog and to enable user interactions with the buttons on the lower side of the window
while(TRUE) {
gint run = gtk_dialog_run (window_main);
if (run == GTK_RESPONSE_APPLY) {
gboolean success = start_long_operation();
}
else if (run == GTK_RESPONSE_HELP) {
open_about();
}
else if (run == GTK_RESPONSE_CANCEL) {
stop_long_operation();
}
else {
gtk_widget_destroy (window_main);
return;
}
}
我已经声明了一个全局变量busy_state
,它由long操作的函数检查:如果它是TRUE,那么内部循环就会继续循环。否则,循环退出,函数返回结果。
stop_long_operation()
只是将此全局变量设置为FALSE。
如前所述,我不能按“停止”按钮并“发送”GTK_RESPONSE_CANCEL直到操作完成,因为它会阻止整个窗口。
我已尝试在while (g_main_context_iteration(NULL, FALSE))
函数中使用stop_long_operation()
技巧,如gtk的文档中所述,但没有结果。
我真的需要设置多线程功能吗?我可以避免这个吗? 谢谢你的帮助。
答案 0 :(得分:2)
如果您可以将长时间操作分解为多个较小的任务,则可以避免使用线程。最简单的方法是创建一个您将传递给g_idle_add(或g_idle_add_full)的回调。每次回调运行时,它都会执行少量工作,然后返回TRUE。任务完成后,返回FALSE并且不再运行回调。如果要中断任务,只需将g_idle_add返回的值传递给g_source_remove即可删除回调。
如果你无法分解操作,那么线程几乎是你唯一的选择。 g_thread_new是执行此操作的低级方法,但使用GThreadPool通常更容易。更高级的选项是使用g_simple_async_result_run_in_thread。
答案 1 :(得分:1)
如果你不想使用线程,这是另一种选择(虽然你应该使用线程,这是非常不安全的):
使用流程。流程要简单得多,可以让您获得更大的灵活性。这是你需要做的:
spawn()
或popen()
kill()
调用或Win32终止函数来终止该进程。您可以在UNIX上使用SIGTERM
并注册处理程序,以便可以进行受控关闭。