C語言實現多線程定時器實例講解
1. 大致功能介紹
- 實現任務列表,定時器會間隔一段時間遍歷列表發現要執行的任務
- 任務列表中的所有任務並行執行
- 每個任務都可以有自己的定時器,並且可以選擇是否要重復執行
- 定義方便的任務函數實現接口
- 定時器可以由用戶自定義何時啟動和停止
- 提供等待功能,保證任務列表中的所有任務執行完成
- 提供任務列表的傳參功能
2. API庫介紹
void setTick(int val);
設置定時間的間隔時間tick,若設置tick為1000,且任務的定時器時間為1000,則任務會在1秒後執行,默認tick為1秒,最小tick時間為1us。
void addTimerTask(TimerTask task, int val, int autoreset, void *arg);
向任務列表註冊一個任務,並指定其定時時間val,以及是否要重復執行autoreset,並可以指定參數的地址。
task需要按照頭文件提供的宏來編寫,例如:
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。
void TimerWait();
用於等待任務列表中所有任務執行完畢。
void TimerStop();
用於停止定時器。
void StartTimer();
用於啟動定時器。
3. 一個例子
#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); }
運行結果:
4. 庫文件源碼
timer.h:
#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
#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語言如何實現多線程定時器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!