1. 程式人生 > 程式設計 >C語言實現多執行緒定時器例項講解

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,NULL);

	//啟動定時器
 StartTimer();
 printf("Timer is started\n");
 //程式等待5秒
 sleep(5);
 //停止定時器
 TimerStop();
 //等待所有任務執行完畢
 TimerWait();
 //列印任務二的計算結果
 printf("%d\n",arg.ret);

}

執行結果:

C語言實現多執行緒定時器例項講解

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,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,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,EventLoop,NULL)){
  printf("Failed to create loop task.\n");
 }
}

注意事項

  • 編譯要加 -l pthread選項
  • 庫實現在Linux環境,如果是windows需要修改執行緒建立函式,休眠函式以及相應的標頭檔案。

到此這篇關於C語言實現多執行緒定時器例項講解的文章就介紹到這了,更多相關C語言如何實現多執行緒定時器內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!