Timeout 與 Idle

引用自:

http://caterpillar.onlyfun.net/Gossip/GTKGossip/TimeoutIdle.html

 

如果您要定時讓程式去作某件事,則可以使用g_timeout_add()或g_timeout_add_full(),g_timeout_add()的定義如下:

guint g_timeout_add(guint interval,
                    GSourceFunc function,
                    gpointer data);


第一個參數是時間間隔,以毫秒為單位,第二個參數是時間到的回呼函式,第三個參數是傳給回呼函式的資料,以
內 建 Signal 的發射與停止 中的範例來說,可以使用g_timeout_add()改寫如下而執行結果相同:

  • g_timeout_demo.c

#include <gtk/gtk.h>

gboolean timeout_callback(GtkButton *button) {

static gint count = 0;
if(count < 5) {
g_signal_emit_by_name(button, "clicked");
count++;
return TRUE;
}
else {
return FALSE;
}
}
// 自訂Callback函式 void button_clicked(GtkWidget *button, gpointer data) { g_print("按鈕按下:%s\n", (char *) data); } int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "哈囉!GTK+!"); button = gtk_button_new_with_label("按我"); gtk_container_add(GTK_CONTAINER(window), button); g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(button_clicked), "哈囉!按鈕!"); g_timeout_add(1000, (GSourceFunc) timeout_callback, button); gtk_widget_show(window); gtk_widget_show(button); gtk_main(); return 0; }


在回呼函式中,若傳回TRUE則繼續下一次計時,
計時器的下一次計時,會是在回呼函式執行完畢後開始, 傳回FALSE則計時器結束並自動銷毀,若您使用 g_timeout_add_full():

guint g_timeout_add_full(gint priority,
                         guint interval,
                         GSourceFunc function,
                         gpointer data,
                         GDestroyNotify notify);


第一個參數為時間到時的執行優先權,可以設定的優先權如下:

  • G_PRIORITY_HIGH
  • G_PRIORITY_DEFAULT(預設)
  • G_PRIORITY_HIGH_IDLE
  • G_PRIORITY_DEFAULT_IDLE
  • G_PRIORITY_LOW


最後一個參數則是計時器被移除時要執行的函式。

相對於計時重複執行某個動作,您可以使用g_idle_add()或g_idle_add_full()函式,讓程式在沒有什麼事情作的時候(例如沒有任何使用者操作,沒有任何需要運算的程式碼時),也可以作一些事情,若使用g_idle_add():

guint g_idle_add(GSourceFunc function,
                 gpointer data);


第一個參數是回呼函式,第二個參數是傳遞給回呼函式的資料,例如下面這個範例,在使用者不作任何事時,就會執行指定的idle函式,而按下按鈕時就執行按鈕的回呼函式:

  • g_idle_demo.c
#include <gtk/gtk.h>

gboolean idle_callback(gpointer data) {

g_print("%s。。XD\n", data);
return TRUE;
} void button_pressed(GtkButton *button, gpointer data) { int i; for(i = 0; i < 10; i++) { g_print("%s...\n", data); sleep(1); } } int main(int argc, char *argv[]) { GtkWidget *window; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "GTimer"); gtk_window_set_default_size(GTK_WINDOW(window), 150, 50); button = gtk_button_new_with_label("按我"); gtk_container_add(GTK_CONTAINER(window), button); g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(button_pressed), "do something"); g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_idle_add((GSourceFunc) idle_callback, "無事可作"); gtk_widget_show_all(window); gtk_main(); return 0; }


同樣的,指定的idle函式若傳回FALSE則會移除idle功能,若是使用
g_idle_add_full():

guint g_idle_add_full(gint priority,
                      GSourceFunc function,
                      gpointer data,
                      GDestroyNotify notify);



其上的參數與g_timeout_add_full()類似。

 

我们知道 glib 提供了一个名为 g_idle_add 的函数,这个函数的功能很容易理解:增加一个空闲任务,让应用程序在空闲时执行指定的函数。这种机制非常有用,如果没有这种机制,很多事情将非常麻烦。它的功能虽然简单,但并不是所有人都知道如何充分发挥它的潜力,这里说说它的几个主要用途吧。

 

1.          在空闲时执行低优先级任务。有的任务优先级比较低,但费耗时间比较长,像屏幕刷新等操作,我们不希望它阻碍当前操作太久,此时可以把它放到空闲任务里去做。实际上 GTK+ 里面也是这样做的,这样可以获得更好的响应性。

 

2.          将同步操作异步化。我们知道在 GTK+ 中,它使用 glib signal 作为窗口 / 控件之间的通信方式, signal 的执行是直接调用函数,即整个 signal 的执行过程是同步完成的。这在多数情况下工作得很好,但有时会出现重入的问题,你调我,我再调你,可能会遇到麻烦。此时我们不得不采用异步方式,而 GTK+ 没有提供像 Win32 下的 PostMessage 之类的异步消息,幸好我们可以用 g_idle_add 函数来模拟。

 

3.          串行化对 GUI 的访问。在大多数平台下,对 GUI 资源的访问都是需要串行化的,即在一个 GUI 应用程序中,只有一个线程可以直接操作 GUI 资源。这是因为出于效率的考虑, GUI 资源是没有加锁保护的, GTK+ 也是这样的。如果另外一个线程要访问 GUI 资源,比如要显示一条信息,怎么办呢?这可以通过 g_idle_add 增加一个空闲任务来实现, idle 任务是 GUI 线程 ( 主线程 ) 中执行的,所以串行了对 GUI 资源的访问。

 

这里要注意, idle 任务并不是一个独立的线程或者进程,而在是主线程中执行的。所谓空闲是指,当 main loop 没有其它消息要处理,而且没有更高优先级的工作要做时,就认为处于空闲状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值