1

我正在扩展一个 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由长操作的函数检查的全局变量:如果它是 TRUE,则内部循环继续循环。否则,循环退出并且函数返回结果。

stop_long_operation()只需将此全局变量设置为 FALSE。

如前所述,在操作完成之前,我无法按下“停止”按钮和“发送”GTK_RESPONSE_CANCEL,因为它阻塞了整个窗口。

我已经尝试在函数while (g_main_context_iteration(NULL, FALSE))内部使用技巧stop_long_operation(),如 gtk's docs 中所述,但没有结果。

我真的需要设置多线程功能吗?我可以避免这种情况吗?谢谢您的帮助。

4

2 回答 2

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

于 2012-07-16T00:25:38.480 回答
1

如果您不想使用线程,这是另一种选择(尽管您应该使用线程,这是非常不安全的):

使用流程。流程要简单得多,并且可以为您提供更大的灵活性。这是您需要做的:

  • 创建另一种 C/C++/任何你想要的语言来完成这个任务的程序
  • 使用spawn()或生成它popen()
  • (可选)使用命令行或 IPC 传递参数
  • 按下按钮时,使用kill()UNIX 上的调用或 Win32 kill 函数来终止进程。您可以SIGTERM在 UNIX 上使用并注册一个处理程序,以便您可以控制关​​闭。
于 2012-07-16T00:31:03.707 回答