【转】gtk+多线程的程序实例
#include <gtk/gtk.h>
gint test()
{
while(1)
{
gdk_threads_enter();
g_printf("hello\n");
gdk_threads_leave();
};
return TRUE;
}
gint timeout_callback( gpointer data )
{
g_thread_create(test, NULL, FALSE, NULL);
return FALSE;
}
/*这是一个回调函数。data参数在本示例中被忽略。
*后面有更多的回调函数示例。*/
void hello( GtkWidget *widget,
gpointer data )
{
g_print ("Hello World\n");
}
gint delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
/*如果你的"delete_event"信号处理函数返回FALSE,GTK会发出"destroy"信号。
*返回TRUE,你不希望关闭窗口。
*当你想弹出“你确定要退出吗?”对话框时它很有用。*/
g_print ("delete event occurred\n");
/*改TRUE为FALSE程序会关闭。*/
return TRUE;
}
/*另一个回调函数*/
void destroy( GtkWidget *widget,
gpointer data )
{
gtk_main_quit ();
}
int main( int argc,
char *argv[] )
{
/* GtkWidget是构件的存储类型*/
GtkWidget *window;
GtkWidget *button;
if(!g_thread_supported()) g_thread_init(NULL);
gdk_threads_init();
/*这个函数在所有的GTK程序都要调 用。参数由命令行中解析出来并且送到该程序中*/
gtk_init (&argc, &argv);
/*创建一个新窗口*/
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/*当窗口收到"delete_event"信号(这个信号由窗口管理器发出,通常是“关闭”
*选项或是标题栏上的关闭按钮发出的),我们让它调用在前面定义的delete_event()函数。
*传给回调函数的data参数值是NULL,它会被回调函数忽略。*/
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (delete_event), NULL);
/*在这里我们连接"destroy"事 件到一个信号处理函数。
*对这个窗口调用gtk_widget_destroy()函数或在"delete_event"回调函数中返回FALSE值
*都会触发这个事件。*/
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
/*创建一个标签为"Hello World"的新按钮。*/
button = gtk_button_new_with_label ("Hello World");
/*当按钮收到"clicked"信 号时会调用hello()函数,并将NULL传给
*它作为参数。hello()函数 在前面定义了。*/
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (hello), NULL);
/*当点击按钮时,会通过调用gtk_widget_destroy(window)来关闭窗口。
* "destroy"信号会从这里或从窗口管理器发出。*/
g_signal_connect_swapped (G_OBJECT (button), "clicked",
G_CALLBACK (gtk_widget_destroy),
window);
/*把按钮放入窗口(一个gtk容器)中。*/
gtk_container_add (GTK_CONTAINER (window), button);
/*最后一步是显示新创建的按钮和窗口*/
gtk_widget_show (button);
gtk_widget_show (window);
gtk_timeout_add(1, timeout_callback, NULL);
/*所有的GTK程序必须有一 个gtk_main()函数。程序运行停在这里
*等待事件(如键盘事件或鼠标 事件)的发生。*/
gdk_threads_enter();
gtk_main ();
gdk_threads_leave();
return 0;
}
#include <gtk/gtk.h>
static GtkWidget *fixed;
static GtkWidget *button1;
static GtkWidget *button2;
int running = 1;
void our_thread1(GtkWidget *button)
{
gint x,y,towards;
x=40;
y=40;
towards=1;
while (running)
{
g_usleep(1); //一定要加
gdk_threads_enter(); //在需要与图形窗口交互的时候加
gtk_fixed_move(GTK_FIXED(fixed),button,x,y);
switch(towards)
{
case 1:
x=x+10;
if (x==250) towards=2;
break;
case 2:
y=y+10;
if (y==250) towards=3;
break;
case 3:
x=x-10;
if (x==40) towards=4;
break;
case 4:
y=y-10;
if (y==50) towards=5;
}
gdk_threads_leave(); //搭配上面的
}
}
void on_begin(GtkWidget* button,gpointer data)
{
gtk_widget_set_sensitive(button,FALSE);
g_thread_create(our_thread1,button1,FALSE,NULL);
}
void *run_f(GtkWidget *butt,gpointer data)
{
running = 0;
}
int main(int argc,char* argv[])
{
GtkWidget *window,*view;
GtkWidget *vbox,*button,*label;
if (!g_thread_supported())
g_thread_init(NULL);
gdk_threads_init();
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"thread apllication");
g_signal_connect(G_OBJECT(window),"delete_event",
G_CALLBACK(gtk_main_quit),NULL);
gtk_container_set_border_width(GTK_CONTAINER(window),10);
vbox=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window),vbox);
label=gtk_label_new("Notice! Button is moving");
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);
view=gtk_viewport_new(NULL,NULL);
gtk_box_pack_start(GTK_BOX(vbox),view,FALSE,FALSE,0);
fixed=gtk_fixed_new();
gtk_widget_set_usize(fixed,330,330);
gtk_container_add(GTK_CONTAINER(view),fixed);
button1=gtk_button_new_with_label("1");
gtk_fixed_put(GTK_FIXED(fixed),button1,10,10);
button=gtk_button_new_with_label("Start");
gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,5);
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(on_begin),NULL); // call on_begin
GtkWidget *run = gtk_button_new_with_label("stop");
gtk_box_pack_start(GTK_BOX(vbox),run,FALSE,FALSE,5);
g_signal_connect(G_OBJECT(run),"clicked",
G_CALLBACK(run_f),NULL); // call on_begin
gtk_widget_show_all(window);
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return FALSE;
}
我们知道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没有其它消息要处理,而且没有更高优先级的工作要做时,就认为处于空闲状态。
网上各种文章都强烈建议,所有对于GUI的操作都在一个线程内完成,其他可能导致阻塞的工作在另外一个线程中。
所以
gdk_threads_enter();
gtk_label_set_text(GTK_LABEL(wbus->time),text);
gdk_threads_leave();
这样的代码应该替换为:
g_idle_add(on_finish, wbus);//子线程中。
gboolean on_finish(gpointer wbus)
{
gtk_label_set_text(GTK_LABEL(wbus->time),text);
return FALSE;
}
【转】gtk+多线程的程序实例的更多相关文章
- 编写Java程序,实现多线程操作同一个实例变量的操作会引发多线程并发的安全问题。
查看本章节 查看作业目录 需求说明: 多线程操作同一个实例变量的操作会引发多线程并发的安全问题.现有 3 个线程代表 3 只猴子,对类中的一个整型变量 count(代表花的总数,共 20 朵花)进行操 ...
- [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)
[.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...
- java Socket多线程聊天程序
参考JAVA 通过 Socket 实现 TCP 编程 参考java Socket多线程聊天程序(适合初学者) 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包 ...
- 线程模型、pthread 系列函数 和 简单多线程服务器端程序
一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属于1:1模型. (一).N:1用户线程模型 “线程实现”建立在“进程控制”机制之上,由用 ...
- 用Java实现多线程服务器程序
一.Java中的服务器程序与多线程 在Java之前,没有一种主流编程语言能够提供对高级网络编程的固有支持.在其他语言环境中,实现网络程序往往需要深入依赖于操作平台的网络API的技术中去,而Java提供 ...
- C#中构建多线程应用程序[转]
原文:http://blog.sina.com.cn/s/blog_4e61c4290100ndyl.html C#中构建多线程应用程序[转] (2011-01-04 21:29:29) 转载▼ 标签 ...
- [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)
[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...
- [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)
[.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...
- posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序
posix 线程(一):线程模型.pthread 系列函数 和 简单多线程服务器端程序 一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属 ...
随机推荐
- DSP下的#program
2014年7月22日 最近调试使用TMS320C6713的片子调试SDRAM,中间经过很多波折,这里就不吐槽了. 想将数据或者代码放到SDRAM上一定要用到#pragma .查阅资料后,感觉百度文库的 ...
- AngularJS作出简单聊天机器人
简单聊天机器人 很初级的对话框形式.以前做对话框使用js,今天尝试使用AngularJS做出来 这里直接使用自己写的JSON数据. <!DOCTYPE html> <html lan ...
- IOS系列swift语言之课时八
这节课需要讲的就是可选链,内存管理,引用计数,unowned解决 //: Playground - noun: a place where people can play import UIKit / ...
- Git项目存放位置在导入Eclipse前不能存放在Eclipse Workspace
这篇帖子的背景: 本人想将一个git项目导入至Eclipse的Workspace中,并且该项目的所有git信息.但是,该git项目在导入之前,就已经存放在Eclipse的Workspace中.在将该g ...
- 【BZOJ3123】森林(主席树,启发式合并)
题意:一个带点权的森林,要求维护以下操作: 1.询问路径上的点权K大值 2.两点之间连边 n,m<=80000 思路:如果树的结构不发生变化只需要维护DFS序 现在因为树的结构发生变化,要将两棵 ...
- IT行业果真跳槽快吗?
近年来IT行业越来越火爆,许多人也开始炒,月入万元不是梦,随随便便拿高薪之类的文章层出不穷,许多的青少年甚至中年人开始关注这块,许多人选择去学习it行业,也朝着月入万元的目标前进,然而,曾几何时,月入 ...
- Linux 下的dd命令使用详解(摘录)
一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512:c=1:k=1024:w=2 参数注释: 1. ...
- [整理]Matlab之中心平滑滤波
滑动平均(moving average):在地球物理异常图上,选定某一尺寸的窗口,将窗口内的所有异常值做算术平均,将平均值作为窗口中心点的异常值.按点距或线距移动窗口,重复此平均方法,直到对整幅图完成 ...
- mysql从零开始
常用的数据库有哪些? oralce,sqlserver,mysql,db2 有钱就用oracle吧 oracle和mysql的区别:https://zhidao.baidu.com/question/ ...
- HTTP、TCP、UDP以及SOCKET之间的区别/联系
一.TCP/IP代表传输控制协议/网际协议,指的是一系列协组. 可分为四个层次:数据链路层.网络层.传输层和应用层. 在网络层:有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在 ...