服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言实现多线程定时器实例讲解

C语言实现多线程定时器实例讲解

2021-10-18 14:07chegxy C/C++

在本篇文章里小编给各位分享的是一篇关于C语言实现多线程定时器实例讲解内容,有需要的朋友们可以参考学习下。

1. 大致功能介绍

  • 实现任务列表,定时器会间隔一段时间遍历列表发现要执行的任务
  • 任务列表中的所有任务并行执行
  • 每个任务都可以有自己的定时器,并且可以选择是否要重复执行
  • 定义方便的任务函数实现接口
  • 定时器可以由用户自定义何时启动和停止
  • 提供等待功能,保证任务列表中的所有任务执行完成
  • 提供任务列表的传参功能

2. API库介绍

?
1
void setTick(int val);

设置定时间的间隔时间tick,若设置tick为1000,且任务的定时器时间为1000,则任务会在1秒后执行,默认tick为1秒,最小tick时间为1us。

?
1
void addTimerTask(TimerTask task, int val, int autoreset, void *arg);

向任务列表注册一个任务,并指定其定时时间val,以及是否要重复执行autoreset,并可以指定参数的地址。
task需要按照头文件提供的宏来编写,例如:

?
1
2
3
4
5
6
7
8
TASK_START(test2, arg)
 
    //body
 Arg *temp = (Arg*)arg;
 temp->ret = temp->a + temp->b;
 printf("This is a test2\n");
 
TASK_END

TASK_START(name, arg)是任务头,name是任务名,arg是参数地址,TASK_END是任务结尾。任务体内可编写正常的c语言代码,并使用参数arg指针。

autoreset有两个可选项:AUTORESET(重复执行),NORESET(执行一次)。

若没有参数,可将arg参数设置为NULL。

?
1
void TimerWait();

用于等待任务列表中所有任务执行完毕。

?
1
void TimerStop();

用于停止定时器。

?
1
void StartTimer();

用于启动定时器。

3. 一个例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include "timer.h"
 
typedef struct Argument{
 int a;
 int b;
 int ret;
}Arg;
 
//任务1,打印语句
TASK_START(test1, arg)
 printf("This is a test1\n");
TASK_END
 
//任务2,计算arg中两个数的和,打印语句
TASK_START(test2, arg)
 
 Arg *temp = (Arg*)arg;
 temp->ret = temp->a + temp->b;
 printf("This is a test2\n");
 
TASK_END
 
//任务3,打印语句
TASK_START(test3, arg)
 printf("This is a test3\n");
TASK_END
 
void main(){
 
 Arg arg;
 
    //设置tick 为 500ms
 setTick(500 * 1000);
 
    //添加任务1到任务列表,设置定时器时间为2.5s,重复执行,无参数
 addTimerTask(test1, 5, AUTORESET, NULL);
 arg.a = 2; arg.b = 3;
 //添加任务2到任务列表,设置定时器时间为0.5s,不重复执行,参数为arg
 addTimerTask(test2, 1, NORESET, &arg);
 //添加任务3到任务列表,设置定时器时间为1s,重复执行,无参数
 addTimerTask(test3, 2, AUTORESET, NULL);
 
    //启动定时器
 StartTimer();
 printf("Timer is started\n");
 //程序等待5秒
 sleep(5);
 //停止定时器
 TimerStop();
 //等待所有任务执行完毕
 TimerWait();
 //打印任务二的计算结果
 printf("%d\n", arg.ret);
 
}

运行结果:

C语言实现多线程定时器实例讲解

4. 库文件源码

timer.h:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef TIMER_H
#define TIMER_H
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#define AUTORESET 1
#define NORESET 0
#define TASK_START(name, arg) void* name(void *arg){
#define TASK_END return NULL;}
typedef void* (*TimerTask)(void* arg);
struct TaskItem{
 TimerTask task;
 int init_counter;
 int counter;
 pthread_t th;
 void *arg;
 void *ret;
 int flag;
 int autoreset;
 struct TaskItem *next;
 
};
void setTick(int val);
void* EventLoop(void* arg);
void addTimerTask(TimerTask task, int val, int autoreset, void *arg);
void TimerWait();
void TimerStop();
void StartTimer();
#endif //TIMER_H

timer.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "timer.h"
#define STOPFLAG 0
#define RUNFLAG 1
static int tick = 1000 * 1000;
static struct TaskItem head = {
 .next = NULL,
};
static pthread_t loop_thread;
static int flag = STOPFLAG;
static int tasknum = 0;
 
void setTick(int val){
 tick = val;
}
void* EventLoop(void* arg){
 
 struct TaskItem *task = head.next;
 struct TaskItem *pretask = &head;
 
 while(flag == RUNFLAG && tasknum > 0){
  
  while(task != NULL){
   if(task->counter == 0){ // it is time for doing task
    if(task->flag == STOPFLAG){ // task is not created
     if(0 != pthread_create(&(task->th), NULL, task->task, task->arg)){ // do a task
      printf("Failed to create user's task");
     }
     else{
      task->flag = RUNFLAG;
     }
    }
    else{
     if(0 != pthread_kill(task->th, 0)){ // current task is completed
      if(task->autoreset == AUTORESET){ // repeat execute
       task->counter = task->init_counter;
       task->flag = STOPFLAG;
      }
      else{ // delete a task
       pretask->next = task->next;
       free(task);
       task = pretask->next;
       tasknum--;
       continue;
      }
     }
    }
   }
   else{
    task->counter--;
   }
   pretask = pretask->next;
   task = task->next;
  }
  usleep(tick); // sleep a tick
  task = head.next;
  pretask = &head;
 }
 flag = STOPFLAG;
}
void addTimerTask(TimerTask task, int val, int autoreset, void *arg){
 struct TaskItem *node;
 node = (struct TaskItem*)malloc(sizeof(struct TaskItem));
 node->next = head.next;
 head.next = node;
 node->arg = arg;
 node->counter = val;
 node->init_counter = val;
 node->task = task;
 node->flag = STOPFLAG;
 node->autoreset = autoreset;
 tasknum++;
}
void TimerWait(){
 pthread_join(loop_thread, NULL);
}
void TimerStop(){
 flag = STOPFLAG;
}
void StartTimer(){
 flag = RUNFLAG;
 if(0 != pthread_create(&loop_thread, NULL, EventLoop, NULL)){
  printf("Failed to create loop task.\n");
 }
}

注意事项

  • 编译要加 -l pthread选项
  • 库实现在Linux环境,如果是windows需要修改线程创建函数,休眠函数以及相应的头文件。

到此这篇关于C语言实现多线程定时器实例讲解的文章就介绍到这了,更多相关C语言如何实现多线程定时器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/chegxy/p/14223159.html

延伸 · 阅读

精彩推荐
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29