在长时间运行的过程中停止GUI冻结

时间:2014-08-22 08:04:58

标签: c

我的流程需要一段时间(可能需要10分钟)才能完成。当我从我的gtk GUI调用它时,窗口会在大约10秒后锁定(变暗并阻止用户操作)。 我想阻止这种情况发生,但我不确定如何发生。我认为多线程就是答案。 我是多线程的新手,所以我正在寻找解决方案。我基本上只是试图阻止GUI锁定,所以我可以使用进度条进行更新,让用户使用取消按钮。

扫描调谐器频率的代码:

int tuner_get_signal (void)
{
    ..........................

    return tuner.signal >> 13;
}


int tuner_check_station (float freq)
{
    static int a, b;
    static float last;
    int signal;

    signal = tuner_get_signal ();

    if (last == 0.0f)
        last = freq;

    if ((a + b + signal > 8) && (fabsf (freq - last) > 0.25f)) {
        a = b = 0;
        last = freq;
        return 1;
    }
    a = b;
    b = signal;

    return 0;
}

我怀疑我需要为tuner_get_signal()函数

创建线程

和扫描功能

typedef struct {
    GtkWidget *dialog;
    GtkWidget *label;
    GtkWidget *progress;
    GList     *stations;
} FreqScanData;


gboolean scan_cb (gpointer data)
{
    static gfloat  freq = FREQ_MIN - 4.0f/20;
    FreqScanData  *fsd = data;

    if (freq > 108) {
        gtk_widget_destroy (fsd->dialog);
        timeout_id = 0;
        return FALSE;
    }

    if (tuner_check_station (freq)) {
        gfloat *f;

        f = g_malloc (sizeof (gfloat));

        *f = freq;
        fsd->stations = g_list_append (fsd->stations, f);
    }

    gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (fsd->progress),
                   MAX (0, (freq - 87.5) / (108 - 87.5)));

    freq += 1.0/20;
    tuner_set_freq (freq);

    return TRUE;
}

用以下方式调用:

timeout_id = g_timeout_add (50, (GSourceFunc)scan_cb, (gpointer)&data);

1 个答案:

答案 0 :(得分:1)

您的问题的明显解决方案是多线程(计算的背景)。最好也使用Gtk +功能(如您在示例解决方案中所示)。

但是,如果您的程序相当简单,并且您不想让它变得复杂(尤其是结果通信,取消等),您也可以经常中断扫描程序以处理Gtk +事件。请参阅events_pending()的文档: http://www.gtk.org/api/2.6/gtk/gtk-General.html#gtk-events-pending

显然,多线程解决方案的整体性能更好,特别是现在大多数计算机都配备了多个CPU内核。