news 2026/1/1 1:15:02

定时器函数g_timeout_add_seconds使用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
定时器函数g_timeout_add_seconds使用详解

g_timeout_add_seconds()是 GLib 库中的一个函数,用于在指定秒数后执行回调函数。它是 GTK+/GLib 应用程序中常用的定时器函数。

函数原型

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

参数说明

interval

  • 类型:guint(无符号整数)

  • 说明: 时间间隔,单位为秒

  • 注意: 实际触发时间可能会有微小延迟,精度不如g_timeout_add()

function

  • 类型:GSourceFunc(函数指针)

  • 说明: 要执行的回调函数

  • 函数签名:gboolean callback(gpointer data)

  • 返回值:

    • TRUE: 继续执行定时器

    • FALSE: 停止定时器

data

  • 类型:gpointer(通用指针)

  • 说明: 传递给回调函数的用户数据

返回值

  • 类型:guint

  • 说明: 事件源ID,可用于取消定时器

基本用法示例

#include <glib.h> #include <stdio.h> gboolean my_callback(gpointer data) { static int count = 0; printf("回调函数被调用,计数: %d\n", ++count); // 执行5次后停止 if (count >= 5) { printf("停止定时器\n"); return FALSE; // 返回FALSE停止定时器 } return TRUE; // 返回TRUE继续定时器 } int main() { // 每2秒执行一次回调函数 guint timer_id = g_timeout_add_seconds(2, my_callback, NULL); // 创建主循环 GMainLoop *loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); return 0; }

g_timeout_add()的区别

// 毫秒级精度 guint g_timeout_add(guint interval, // 毫秒 GSourceFunc function, gpointer data); // 秒级精度(优化功耗) guint g_timeout_add_seconds(guint interval, // 秒 GSourceFunc function, gpointer data);

主要区别:

  1. 精度:g_timeout_add()使用毫秒,g_timeout_add_seconds()使用秒

  2. 功耗:g_timeout_add_seconds()在移动设备上更节能

  3. 系统唤醒:g_timeout_add_seconds()会合并多个定时器,减少系统唤醒次数

高级用法

1. 传递参数给回调函数

typedef struct { int max_count; char *message; } MyData; gboolean callback_with_data(gpointer user_data) { MyData *data = (MyData *)user_data; static int count = 0; printf("%s - 调用次数: %d/%d\n",>static guint timer_id = 0; gboolean my_callback(gpointer data) { printf("定时器执行\n"); return TRUE; } void start_timer() { timer_id = g_timeout_add_seconds(1, my_callback, NULL); } void stop_timer() { if (timer_id > 0) { g_source_remove(timer_id); timer_id = 0; } }

3. 一次性定时器

gboolean one_shot_callback(gpointer data) { printf("这个函数只执行一次\n"); // 做一些清理工作... g_free(data); return FALSE; // 返回FALSE确保只执行一次 } void schedule_one_shot() { // 5秒后执行一次 g_timeout_add_seconds(5, one_shot_callback, some_data); }

实际应用场景

1. GUI 界面更新

// 定期更新UI状态 gboolean update_ui(gpointer data) { GtkLabel *label = GTK_LABEL(data); time_t now = time(NULL); char buffer[100]; strftime(buffer, sizeof(buffer), "当前时间: %H:%M:%S", localtime(&now)); gtk_label_set_text(label, buffer); return TRUE; // 继续更新 } // 每秒更新一次时间显示 gtk_timeout_add_seconds(1, (GSourceFunc)update_ui, label);

2. 网络请求重试

gboolean retry_network_request(gpointer data) { HttpRequest *request = (HttpRequest *)data; if (request->retry_count >= MAX_RETRIES) { g_signal_emit(request, "failed", 0); g_object_unref(request); return FALSE; } if (send_http_request(request)) { g_object_unref(request); return FALSE; } request->retry_count++; return TRUE; // 继续重试 } void send_request_with_retry(HttpRequest *request) { // 每10秒重试一次 g_timeout_add_seconds(10, retry_network_request, g_object_ref(request)); }

3. 自动保存功能

gboolean autosave_document(gpointer data) { Document *doc = (Document *)data; if (doc->modified) { save_document(doc); doc->modified = FALSE; printf("文档已自动保存\n"); } return TRUE; } void enable_autosave(Document *doc) { // 每30秒自动保存一次 g_timeout_add_seconds(30, autosave_document, doc); }

注意事项

  1. 线程安全: 回调函数在主线程中执行,如果需要进行耗时操作,应考虑使用线程

  2. 内存管理: 传递动态分配的数据时,需要确保适当释放

  3. 精度限制: 秒级定时器不适合高精度需求

  4. 功耗优化: 在移动应用中优先使用g_timeout_add_seconds()

  5. 主循环: 必须有正在运行的GMainLoop才能触发定时器

常见问题解决

问题1: 定时器不触发

原因: 没有运行主事件循环

// 错误:没有主循环 g_timeout_add_seconds(1, callback, NULL); // 这里缺少 g_main_loop_run() // 正确:运行主循环 GMainLoop *loop = g_main_loop_new(NULL, FALSE); g_timeout_add_seconds(1, callback, NULL); g_main_loop_run(loop);

问题2: 内存泄漏

// 错误:可能的内存泄漏 g_timeout_add_seconds(1, callback, g_strdup("data")); // 正确:在回调中释放 gboolean callback(gpointer data) { char *str = (char *)data; printf("%s\n", str); g_free(str); // 记得释放 return FALSE; }

问题3: 回调函数中修改UI

// 错误:在非主线程中更新UI gboolean update_ui(gpointer data) { // 如果在其他线程中执行,这可能导致问题 gtk_label_set_text(GTK_LABEL(data), "更新文本"); return FALSE; } // 正确:使用 g_idle_add() 确保在主线程中更新UI gboolean update_ui_safe(gpointer data) { g_idle_add((GSourceFunc)actual_ui_update, data); return FALSE; }

g_timeout_add_seconds()是 GLib 中非常实用的定时器函数,特别适合需要定期执行任务但又不需要高精度的场景。正确使用时,可以大大简化应用程序的定时任务管理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/29 14:54:26

广州某公司百度地图风格切片并私有化部署项目

在国产的互联网地图中&#xff0c;百度地图、高德地图、腾讯地图和天地图应该是你比较熟悉的。 其中百度地图、高德地图和腾讯地图是各大互联网巨头旗下的商业地图&#xff0c;早期因为政策原因都分别对地图坐标进行了加密处理。 高德地图和腾讯地图直接采用国测局的GCJ02坐标…

作者头像 李华
网站建设 2025/12/29 14:50:29

git reset回退版本:在PyTorch-CUDA-v2.7中恢复稳定环境

Git Reset 回退版本&#xff1a;在 PyTorch-CUDA-v2.7 中恢复稳定环境 在深度学习项目开发中&#xff0c;一个常见的困境是&#xff1a;你刚刚完成了一次模型结构的重构&#xff0c;满怀期待地启动训练&#xff0c;结果却遭遇了 CUDA out of memory 或模块导入失败。更糟的是&a…

作者头像 李华
网站建设 2025/12/31 9:36:16

PyTorch-CUDA-v2.7镜像赋能大模型token批量生成服务

PyTorch-CUDA-v2.7镜像赋能大模型token批量生成服务 在当前AI工业化落地加速的背景下&#xff0c;如何高效、稳定地部署大规模语言模型&#xff08;LLM&#xff09;推理服务&#xff0c;已成为许多团队面临的核心挑战。尤其是在需要处理海量文本请求的场景下——比如内容生成、…

作者头像 李华
网站建设 2025/12/29 14:45:43

基于单片机远程数据采集系统仿真设计

**单片机设计介绍&#xff0c;基于单片机远程数据采集系统仿真设计 文章目录一 概要二、功能设计设计思路三、 软件设计原理图五、 程序六、 文章目录一 概要 基于单片机远程数据采集系统的仿真设计概要主要涉及到单片机控制技术、传感器技术、远程通信技术和仿真技术等多个方面…

作者头像 李华
网站建设 2025/12/29 14:44:53

这条 sed 命令为什么在你电脑能跑,在服务器直接炸?

如果你写过 sed&#xff0c;一定见过这个报错&#xff1a; sed: Invalid range end奇怪的是——同一条命令&#xff1a;在你本机能跑&#xff0c;换一台服务器直接报错&#xff0c;稍微调一下字符顺序&#xff0c;报错没了&#xff0c;结果却 完全不对。 于是很多人开始怀疑人…

作者头像 李华