C语言实现定时器,定时触发函数

最近想到使用C语言实现一个简单的定时器。使用操作系统windows.h提供的多线程API就能实现
首先定义一个定时器结构体,包含定时时间和触发的函数指针

typedef struct Stimer{
    int valid;//定时器有效
    long timingMS;//定时时间
    TriggerFunc tf;//触发函数
}Stimer;

创建一个线程函数,用来运行定时器

DWORD WINAPI timer_thread(LPVOID lpParam){

    Stimer *st = (Stimer*)lpParam;

    long waitTime = st->timingMS;//获取定时间隔
    TriggerFunc tf = st->tf;//获取触发函数


	do{
		Sleep(waitTime);//休眠
		if(!st->valid){//判断定时器有效性
            break;
		}
        tf();//执行函数
	}while(1);
}

新建定时器的函数

Stimer* new_timer(){

    Stimer *st = malloc(sizeof(Stimer));
    st->valid = 0;
    st->timingMS = 0;
    st->tf = NULL;

    return st;
}

添加函数设置定时器的参数


void set_timer_timing(Stimer* st, long t){
    st->timingMS = t;
}
void set_timer_trigger_func(Stimer* st, TriggerFunc t){
    st->tf = t;
}

通过创建一个线程来运行定时器

void start_timer(Stimer* st){
    if(st->timingMS <= 0 || st->tf == NULL){
        return;
    }else{
        st->valid = 1;
    }
    //创建定时器线程
	DWORD threadID;
	HANDLE hThread = CreateThread(NULL,0,timer_thread,(LPVOID)st,0,&threadID);
}

对于定时器的停止,只需要改变它的有效标志


void stop_timer(Stimer* st){
    st->valid = 0;
}

定时器是动态分配的空间,最后需要添加一个释放定时器的函数


void release_timer(Stimer *st){
    free(st);
}

完整代码
timer.h

#ifndef _TIMER_H_
#define _TIMER_H_

//定义函数指针类型
typedef void(*TriggerFunc)(void);
//定时器结构体
typedef struct Stimer{
    int valid;//定时器有效
    long timingMS;//定时时间
    TriggerFunc tf;//触发函数
}Stimer;
Stimer* new_timer();//新建定时器
void set_timer_timing(Stimer* st, long t);//设置定时器定时时间
void set_timer_trigger_func(Stimer* st, TriggerFunc t);//设置定时器触发函数
void start_timer(Stimer* st);//启动定时器
void stop_timer(Stimer* st);//停止定时器
void release_timer(Stimer *st);//销毁定时器
#endif // _TIMER_H_

timer.c

#include <windows.h>
#include "timer.h"
//定时器线程
DWORD WINAPI timer_thread(LPVOID lpParam){
    Stimer *st = (Stimer*)lpParam;

    long waitTime = st->timingMS;//获取定时间隔
    TriggerFunc tf = st->tf;//获取触发函数


	do{
		Sleep(waitTime);//休眠
		if(!st->valid){//判断定时器有效性
            break;
		}
        tf();//执行函数
	}while(1);
}
Stimer* new_timer(){

    Stimer *st = malloc(sizeof(Stimer));
    st->valid = 0;
    st->timingMS = 0;
    st->tf = NULL;

    return st;
}
void set_timer_timing(Stimer* st, long t){
    st->timingMS = t;
}
void set_timer_trigger_func(Stimer* st, TriggerFunc t){
    st->tf = t;
}
void start_timer(Stimer* st){
    if(st->timingMS <= 0 || st->tf == NULL){
        return;
    }else{
        st->valid = 1;
    }
    //创建定时器线程
	DWORD threadID;
	HANDLE hThread = CreateThread(NULL,0,timer_thread,(LPVOID)st,0,&threadID);
}

void stop_timer(Stimer* st){
    st->valid = 0;
}
void release_timer(Stimer *st){
    free(st);
}

测试

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "timer.h"
//测试函数
void test_func1(){
    puts("Function111 is executed");
}
void test_func2(){
    puts("Function222 is executed");
}
int main(){
    //创建2个定时器
    Stimer *st1 = new_timer();
    Stimer *st2 = new_timer();
    //设置定时器1
    set_timer_timing(st1, 400);//定时400ms
    set_timer_trigger_func(st1, test_func1);//定时触发函数
    //设置定时器2
    set_timer_timing(st2, 600);
    set_timer_trigger_func(st2, test_func2);
    //运行定时器
    getch();
    puts("启动定时器1");
    start_timer(st1);
    getch();
    puts("启动定时器2");
    start_timer(st2);
    getch();
    puts("停止定时器1");
    stop_timer(st1);
    getch();
    puts("停止定时器2");
    stop_timer(st2);

    //销毁定时器
    release_timer(st1);
    release_timer(st2);
    getch();
	return 0;
}

结果
在这里插入图片描述
实现的定时器比较简单,没有对调用函数参数的支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/52239.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Sestra 实用教程(三)输入与输出

目 录 一、前言二、分析流程三、输入文件3.1 模型与荷载3.2 分析控制数据 四、输出文件五、参考文献 一、前言 SESAM &#xff08;Super Element Structure Analysis Module&#xff09;是由挪威船级社&#xff08;DNV-GL&#xff09;开发的一款有限元分析&#xff08;FEA&…

解读Spring-context的property-placeholder

在spring中&#xff0c;如果要给程序定义一些参数&#xff0c;可以放在application.properties中&#xff0c;通过<context:property-placeholder>加载这个属性文件&#xff0c;然后就可以通过value给我们的变量自动赋值&#xff0c;如果你们的程序可能运行在多个环境中&…

Qt 5. QSerialPort串口收发

1. 代码 //ex2.cpp #include "ex2.h" #include "ui_ex2.h" #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo>int static cnt 0;Ex2::Ex2(QWidget *parent): QDialog(parent), ui(new Ui::Ex2) {ui->setupUi…

【Golang 接口自动化03】 解析接口返回XML

目录 解析接口返回数据 定义结构体 解析函数&#xff1a; 测试 优化 资料获取方法 上一篇我们学习了怎么发送各种数据类型的http请求&#xff0c;这一篇我们来介绍怎么来解析接口返回的XML的数据。 解析接口返回数据 定义结构体 假设我们现在有一个接口返回的数据resp如…

flutter 打包iOS安装包

flutter iOS Xcode打包并导出ipa文件安装包 1、 Xcode配置 1、 启动打包 1、 等待打包 1、 打包完成、准备导出ipa 1、 选择模式 1、 选择配置文件 1、 导出 1、 选择导出位置 1、 得到ipa

后台管理系统中常见的三栏布局总结:使用element ui构建

vue2 使用 el-menu构建的列表布局&#xff1a; 列表可以折叠展开 <template><div class"home"><header><el-button type"primary" click"handleClick">切换</el-button></header><div class"conte…

小研究 - 主动式微服务细粒度弹性缩放算法研究(三)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放&#xff0c;忽略了能够充分利用单台服务器资源的细粒度垂直缩放&#xff0c;从而导致资源浪费。为此&#xff0c;本文设计了主动式微服务细粒度弹性缩放算法…

webpack联邦模块介绍及在dumi中使用问题整理

文章目录 前言一、ModuleFederationPlugin参数含义&#xff1f;二、如何在dumi中使用及问题整理1. 如何在dumi中使用(这个配置是好使的)2.相关问题整理2.1 问题12.2 问题2 总结 前言 联邦模块&#xff08;Module Federation&#xff09;是指一种用于构建微前端架构的技术&…

Vue3 导出word

&#x1f642;博主&#xff1a;锅盖哒 &#x1f642;文章核心&#xff1a;导出word 目录 1.首先&#xff0c;你需要安装docxtemplater库。可以使用npm或yarn来安装&#xff1a; 2.在Vue组件中&#xff0c;你可以使用docxtemplater来生成Word文档并提供一个导出按钮供用户下载…

[论文笔记] CLRerNet: Improving Confidence of Lane Detection with LaneIoU

Honda, Hiroto, and Yusuke Uchida. “CLRerNet: Improving Confidence of Lane Detection with LaneIoU.” arXiv preprint arXiv:2305.08366 (2023). 2023.05 出的一篇车道线检测的文章, 效果在CULane, CurveLanes SOTA 文章目录 简介LaneIoULineIoU存在问题为什么使用LaneIo…

Elasticsearch:通过动态修剪实现更快的基数聚合

作者&#xff1a;Adrien Grand Elasticsearch 8.9 通过支持动态修剪&#xff08;dynamic pruning&#xff09;引入了基数聚合加速。 这种优化需要满足特定的条件才能生效&#xff0c;但一旦实现&#xff0c;通常会产生惊人的结果。 我们观察到&#xff0c;通过此更改&#xff0…

微软对Visual Studio 17.7 Preview 4进行版本更新,新插件管理器亮相

近期微软发布了Visual Studio 17.7 Preview 4版本&#xff0c;而在这个版本当中&#xff0c;全新设计的扩展插件管理器将亮相&#xff0c;并且可以让用户可更简单地安装和管理扩展插件。 据了解&#xff0c;目前用户可以从 Visual Studio Marketplace 下载各式各样的 VS 扩展插…

【分布鲁棒、状态估计】分布式鲁棒优化电力系统状态估计研究[几种算法进行比较](Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

SpringBoot 8种异步实现方式

前言&#xff1a;异步执行对于开发者来说并不陌生&#xff0c;在实际的开发过程中&#xff0c;很多场景多会使用到异步&#xff0c;相比同步执行&#xff0c;异步可以大大缩短请求链路耗时时间&#xff0c;比如&#xff1a;「发送短信、邮件、异步更新等」&#xff0c;这些都是…

驱动开发 day3 (模块化驱动启动led,蜂鸣器,风扇,震动马达)

模块化驱动启动led,蜂鸣器,风扇,震动马达并加上Makefile 封装模块化驱动&#xff0c;可自由安装卸载驱动&#xff0c;便于驱动更新(附图) 1.安装模块驱动同时初始化各个设备并使能 2.该驱动会自动创建驱动节点. 3.通过c函数程序输入控制各个设备 4.卸载模块驱动 //编译驱动…

Python 日志记录:6大日志记录库的比较

Python 日志记录&#xff1a;6大日志记录库的比较 文章目录 Python 日志记录&#xff1a;6大日志记录库的比较前言一些日志框架建议1. logging - 内置的标准日志模块默认日志记录器自定义日志记录器生成结构化日志 2. Loguru - 最流行的Python第三方日志框架默认日志记录器自定…

Redis(五)—— Redis进阶部分

一、Redis配置文件详解 注意这是Redis服务本身的配置文件&#xff0c;相当于maven的settings.xml&#xff0c;而不是我们在springboot去配置Redis的那个application.yml。 核心部分include 引入其他redis配置文件&#xff0c;相当于spring的<import>bind 设置IP&#xf…

Spring MVC学习笔记,包含mvc架构使用,过滤器、拦截器、执行流程等等

&#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 Spring MVC 习笔记1、Spring MVC demo2、Spring MVC 中常见注解3、数据处理3.1、请求参数处理3.2、响应数据处理 4、RESTFul 风格5、静态资源处理6、HttpMessageConverter 转换器7、过…

在周末,找回属于自己的时间~

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f466;&#x1f3fb;个人主页 &#xff1a; 点击这里 &#x1f4bb;推荐专栏1&#xff1a;PHP面试题专区&#xff08;2023&#xff09; PHP入门基…

词典项目练习

思维导图 客户端 #include "head.h" //用户提示界面 void help_info1() {printf("\t-----------------------------------------------\n");printf("\t| HENRY 在线辞典 |\n");printf("\t|版本:0.0.1 …
最新文章