【转】GTK+主循环(main loop)的工作原理

g_main_loop_run 的简单使用举例 阅读详情

原文: http://blog.chinaunix.net/u3/90973/showart_1876423.html

 

 

GTK+主循环(main loop)的工作原理

开发者在线 Builder.com.cn 更新时间:2008-02-14作者:absurd 来源:优快云

本文关键词: 工作原理 主循环 GTK+

我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下,应用程序处于睡眠状态。

 

因为这种事件驱动机制,GUI应用程序都毫无例外的需要一个主循环(main loop)。主循环(main loop)控制应用程序什么时候进入睡眠状态,什么时候被唤醒。主循环实现得好,应用程序才能工作正常又省电。

 

Win32 GUI应用程序的主循环是我们比较熟悉的,其大致如下:

       // Main message loop:

       while (GetMessage(&msg, NULL, 0, 0))

       {

              if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

              {

                     TranslateMessage(&msg);

                     DispatchMessage(&msg);

              }

       }

 

在这个主循环中,它不断的从消息队列中提取消息,然后分发给消息的目标(通常是窗口),直到GetMessage返回FALSE(收到WM_QUIT消息,一般调用PostQuitMessage)为止,如果队列中没有消息,应用程序就进入睡眠状态。这种方法简单明了,缺陷也是明显的,它只能挂在消息队列上,而不能同时挂在多个事件源上(如管道和socket等)。要挂在多个事件源上,需要使用其它方式,比如用WaitForMultipleObjects,那就比较麻烦了。

 

而在GTK+应用程序中,其主循环(main loop)更加简单,但是非常的不明了:

gtk_main ();

 

不少人用GTK+写了很长时间的程序,还是觉得这行代码很神秘,不知道里面到底干了什么。本文试图分析一下gtk_main的工作原理:

 

gtk_main主要是对glib的main loop的包装,基本上分为三步:

1.         调用初始化函数。

2.         进入glib main loop

3.         调用~初始化函数。

 

所以弄清楚glib main loop之后,gtk_main的实现也就尽收眼底了,本文重点分析glib的main loop的实现。main loop使用模式大致如下:

loop = g_main_loop_new (NULL, TRUE);

g_main_loop_run (loop);

 

g_main_loop_new创建一个main loop对象,一个main loop对象只能被一个线程使用,但一个线程可以有多个main loop对象。在GTK+应用中,一个线程使用多个main loop的主要用途是实现模态对话框,它在gtk_dialog_run函数里创建一个新的main loop,通过该main loop分发消息,直到对话框关闭为止。

 

g_main_loop_run则是进入主循环,它会一直阻塞在这里,直到让它退出为止。有事件时,它就处理事件,没事件时就睡眠。

 

g_main_loop_quit则是用于退出主循环,相当于Win32下的PostQuitMessage函数。

 

Glib main loop的最大特点就是支持多事件源,使用非常方便。来自用户的键盘和鼠标事件、来自系统的定时事件和socket事件等等,还支持一个称为idle的事件源,其主要用途是实现异步事件。Main loop的基本组成如下图所示:

 

GMainLoop的主要部件是GMainContext,GMainContext可以在多个GMainLoop间共享,但要求这些GMainLoop都在同一个线程中运行,前面提到的模态对话框就属于这一类。GMainContext通常由多个GSource组成,GSource是事件源的抽象,任何事件源,只要实现GSource规定的接口,都可以挂到GMainContext中来。

 

GSource的接口函数有:

1.         gboolean (*prepare)  (GSource    *source, gint       *timeout_);进入睡眠之前,在g_main_context_prepare里,mainloop调用所有Source的prepare函数,计算最小的timeout时间,该时间决定下一次睡眠的时间。

2.         gboolean (*check)    (GSource    *source); poll被唤醒后,在g_main_context_check里,mainloop调用所有Source的check函数,检查是否有Source已经准备好了。如果poll是由于错误或者超时等原因唤醒的,就不必进行dispatch了。

3.         gboolean (*dispatch) (GSource*source, GSourceFunc callback,gpointer user_data); 当有Source准备好了,在g_main_context_dispatch里,mainloop调用所有Source的dispatch函数,去分发消息。

4.         void     (*finalize) (GSource    *source); 在Source被移出时,mainloop调用该函数去销毁Source。

 

Main loop的工作流程简图如下:

 

 

下面我们看看几个内置Source的实现机制:

Idle 它主要用实现异步事件,功能类似于Win32下的PostMessage。但它还支持重复执行的特性,根据用户注册的回调函数的返回值而定。

1.         g_idle_prepare把超时设置为0,也就是即时唤醒,不进入睡眠状态。

2.         g_idle_check 始终返回TRUE,表示准备好了。

3.         g_idle_dispatch 调用用户注册的回调函数。

 

Timeout 它主要用于实现定时器,支持一次定时和重复定时,根据用户注册的回调函数的返回值而定。

1.         g_timeout_prepare 计算下一次的超时时间。

2.         g_timeout_check 检查超时时间是否到了,如果到了就返回TRUE,否则返回FALSE。

3.         g_timeout_dispatch调用用户注册的回调函数。

 

线程可以向自己的mainloop中增加Source,也可以向其它线程的mainloop增加Source。向自己的mainloop中增加Source时,mainloop已经唤醒了,所以不会存在什么问题。而向其它线程的mainloop增加Source时,对方线程可能正挂在poll里睡眠,所以要想法唤醒它,否则Source可能来不及处理。在Linux下,这是通过wake_up_pipe管道实现的,mainloop在poll时,它除了等待所有的Source外,还会等待wake_up_pipe管道。要唤醒poll,调用g_main_context_wakeup_unlocked向wake_up_pipe里写入字母A就行了。

 

 

GTK搭建数采程序的多线程解决方法 http://stackoverflow.com/questions/8826523/gtk-main-and-unix-sockets 在stackoverflow上 阅读详情

相关推荐

通讯软件013——分分钟学会Kepware OPC AE Server仿真配置

本文介绍如何使用Kepware软件仿真OPC AE Server配置。

zhouwl72的博客 2226

GTK

模板 #include<gtk/gtk.h> int main(int argc,char *argv[])//头文件 { gtk_init(&argc,&argv);//初始化 //...... //我们所写的代码 //...... gtk_main();//主事件循环 return 0; } 头文件〈gtk/gtk....

高朗的博客 979

手把手教你理解MIS结构C-V特性曲线:从理论到测试实操

本文深入解析了金属-绝缘体-半导体(MIS)结构的电容-电压(C-V)特性曲线,从积累、耗尽到反型等物理状态出发,详细阐述了其测试原理与实操要点。文章重点介绍了如何通过C-V曲线提取氧化层厚度、掺杂浓度、界面态密度等关键参数,并探讨了偏压-温度(B-T)应力实验在揪出可动离子电荷等可靠性问题中的应用,为半导体器件物理研究与工艺评估提供了实用指南。

weixin_29304021的博客 439

GTK+主循环(main loop)的工作原理

GTK+主循环(main loop)的工作原理 转载时请注明出处和作者联系方式:http://blog.youkuaiyun.com/absurd作者联系方式:Li XianJing 更新时间:2007-3-17 我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等

国产开源 GUI 引擎 AWTK 1万+

手把手教程:使用C#实现工业上位机开发

深入讲解如何利用C#进行上位机开发,涵盖通信协议与界面设计,助力掌握工业自动化核心技能。结合实际案例,让上位机开发更高效直观。

weixin_32480007的博客 2064

OpenSceneGraph编译、安装、开发环境

详细描述WIndows 10下使用Visual Studio 2019编译OpenSceneGraph 3.6.5的操作流程

国产CAx(CAD/CAE/CAM)软件研发 8770

glib g_main_loop的简单例子

写了一个应用g_main_loop的简单例子 g_main_loop_new,创建了一个loop对象 g_main_loop_run,当程序运行到这里,就进入了一个死循环,不过添加到loop中的逻辑还是在跑的,必须要有g_main_loop_quit()才能终止循环 main_loop中,我们可以添加异步事件,用来执行回调函数,用到g_idle_add() guint g_idle_ad...

Luobooooo的博客 4845

URDF模型转换实战:解决SolidWorks到Gazebo的五大常见问题

本文详细解析了从SolidWorks导出URDF模型到Gazebo仿真过程中常见的五大问题及解决方案,包括插件安装、坐标系建立、Link与Joint配置等关键步骤。通过实战经验分享,帮助机器人仿真工程师高效完成模型转换,确保Gazebo仿真准确性。

weixin_29052717的博客 442

GTK+主循环 main loop 的工作原理

GTK+主循环 main loop 的工作原理

bgfuufb的博客 223

USLE模型(1.2):LS因子的计算

基于USLE的甘南川西北土壤侵蚀研究。准备好30米分辨率的dem。

所有专家都曾始于新手 3481

把 ABAP 出站 IDoc 做到稳如老狗:从数据抽取到端口投递的全链路拆解

SAP出站IDoc创建流程解析 本文详细拆解了SAP系统中出站IDoc的创建流程,将其归纳为四个关键阶段:数据获取、数据转换、控制记录校验和端口投递。文章指出,IDoc的稳定性取决于整条流水线的设计质量,而不仅仅是字段映射。 核心要点包括: IDoc由控制记录和数据记录组成,需在WE31/WE30中定义段结构 2.数据获取阶段需明确触发点、依赖链和一致性保证 3.数据转换应遵循"结构版本+映射纪律"原则 4.控制记录校验决定IDoc能否发出,需与WE20伙伴配置匹配 5.端口类型(tRF

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 171

GTK+主循环(main loop)的工作原理 [zt]

GTK+主循环(main loop)的工作原理GTK+主循环(main loop)的工作原理 转载时请注明出处和作者联系方式:http://blog.youkuaiyun.com/absurd作者联系方式:Li XianJing <xianjimli at hotmail dot com>更新时间:2007-3-17 我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自...

weixin_34007020的博客 934

ConvNeXt 系列改进:二次创新 ConvNeXt:结合 RepVGG 结构重参数化,训练多分支、推理单路

2026年的视觉模型赛道呈现出一种有趣的“返璞归真”趋势——在Transformer狂飙数年之后,卷积网络正以全新的姿态回归。这其中,ConvNeXt无疑是纯卷积阵营中最耀眼的明星。从2022年Meta AI首次提出至今,ConvNeXt系列已经走过了近四年的演进之路,衍生出ConvNeXt V2、E-ConvNeXt等多个增强版本。ConvNeXt的7×7深度卷积带来了不错的感受野,却也埋下了推理效率的隐患。

ZXSXJ的博客 232

GTK 主循环 main loop 的工作原理

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GTK+主循环(mai

jggyff的博客 354

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

GTK学习(4)-主循环(main loop)的工作原理

GTK+主循环(main loop)的工作原理 我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下,应用程序处于睡眠状态。 因为这种事件驱动机制,GUI应用程序都毫无例外的需要一个主循环(main loop)。主循环(main loop)控...

上善若水 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

GTK+主循环(main loop)及消息机制

一、我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下,应用程序处于睡眠状态。因为这种事件驱动机制,GUI应用程序都毫无例外的需要一个主循环(main loop)。主循环(main loop)控制应用程序什么时候进入睡眠状态,什...

weixin_34082695的博客 666

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Glib学习(2)——main loop

文章目录简介包含文件类型几个函数介绍GThreadFunc () 简介 主事件循环——管理所有可用的事件源 主事件循环管理GLib和GTK+应用程序的所有可用事件源。这些事件可以来自任意数量的不同类型的源,比如文件描述符(纯文件、管道或套接字)和超时。还可以使用g_source_attach()添加新类型的事件源。 为了允许在不同的线程中处理多个独立的源集,每个源都与一个GMainContext相关联。GMainContext只能在单个线程中运行,但是可以向其添加源,并从其他线程中删除源。所有在GMainC

MoL的博客 2482

g_main_loop_new (NULL, FALSE) 原理分析

我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下,应用程序处于睡眠状态。 因为这种事件驱动机制,GUI应用程序都毫无例外的需要一个主循环(main loop)。主循环(main lo

arag2009的学习专栏 1万+
上一篇: 【转】逆向小试 ―― QQ 自动登录器原理分析
下一篇: 【转】玩转ptrace(一)
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值