65.9K
CodeProject 正在变化。 阅读更多。
Home

自制的轻量级调度程序

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.44/5 (9投票s)

2008年2月14日

CPOL

1分钟阅读

viewsIcon

32525

基于定时器的任务调度程序

引言

在某些时候,需要以预定的时间间隔执行任务。这里提供的解决方案是一组 C++ 类,它为 TimerQueue API 提供了一个包装。

使用代码

该调度器由 CTask 类和 CScheduler 类组成... 调度器维护一个任务列表,当与任务关联的计时器到期时,调度器将执行这些任务。当调度器执行任务时,缓存在 CTask 类中的用户定义的的回调函数将被执行。该调度器提供接口来排队新的任务和取消用户排队的任务。

以下是 CTask 类的类声明。

           
//Unit of execution scheduled by CScheduler 
class CTask{

friend VOID CALLBACK CTimerScheduler::WaitOrTimerCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired);

private:
HANDLE hQueueTimer_; //handle to timerqueue for this task
void(*callback_)(void);//user defined callback function
CScheduler& sched_;//the scheduler

public: 
CTask(CScheduler& sched, void(*callback)(void)) :
hQueueTimer_(0), sched_(sched), callback_(callback){}
void setHandle(HANDLE hQueueTimer);
void finish();
};


以下是 CScheduler 类的类声明

     
/*Prototypes of functions to be pulled from kernel32.dll*/

typedef VOID (CALLBACK *WAITORTIMERCALLBACK)(PVOID lpParameter,BOOLEAN TimerOrWaitFired); 

typedef HANDLE (*CREATETIMERQUEUE)(void);

typedef BOOL (CALLBACK *CREATETIMERQUEUETIMER)(
PHANDLE phNewTimer,
HANDLE TimerQueue, 
WAITORTIMERCALLBACK callback,
PVOID Parameter,
DWORD DueTime,
DWORD Period,
ULONG Flags
);

typedef BOOL (CALLBACK *DELETETIMERQUEUETIMER)(
HANDLE TimerQueue,
HANDLE Timer,
HANDLE CompletionEvent
);

typedef BOOL (CALLBACK *DELETETIMERQUEUE)(
HANDLE TimerQueue
);

/**/

class CScheduler{ 
friend CTask;

friend VOID CALLBACK WaitOrTimerCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired);

private:
unsigned long interval_;
list<CTask*> tasks_;
HANDLE hTimer_; 
HMODULE hLibrary_;
static CRITICAL_SECTION cs_;

private:
static VOID CALLBACK WaitOrTimerCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired);

CREATETIMERQUEUE createTimer;

DELETETIMERQUEUE deleteTimerQueue;

CREATETIMERQUEUETIMER createTimerQueueTimer;

DELETETIMERQUEUETIMER deleteTimerQueueTimer;

public: 
~CScheduler();
void start();
void stop();
void enqueueTask(int interval, void (*callback)(void));
void removeTask(CTask* task);
void cancelTasks();
};

要在您的代码中使用这些类,请将代码复制到各自的文件中,并在您的项目中包含它们。

#include <windows.h>
#include "stdafx.h"
#include "Scheduler.h"

void UserSuppliedFunction(){
 static int x = 0; 
 printf("function called %ld\n", ++x);
}
int main(int argc, char* argv[])
{
 CScheduler sched;
 sched.start();
 unsigned int i = 0xFFFFFFFF;
 while( i-- ){
  sched.enqueueTask((i/10000000)*2, UserSuppliedFunction);  
  Sleep(5);
  if( (i%100) == 0 ){
   printf("cancelling....\n");
   sched.cancelTasks();
  }
 }
 sched.cancelTasks();
 sched.stop();
 Sleep(1000);
 return 0;
}
  

以下是类的实现

#include "Scheduler.h"
#include 

CRITICAL_SECTION CScheduler::cs_ ;


void
CScheduler::start(){
    hLibrary_   = LoadLibrary("kernel32");
    createTimer = 
          (CREATETIMERQUEUE)GetProcAddress(hLibrary_, "CreateTimerQueue");
    deleteTimerQueue = 
          (DELETETIMERQUEUE)GetProcAddress(hLibrary_, "DeleteTimerQueue");
    createTimerQueueTimer = 
     (CREATETIMERQUEUETIMER)GetProcAddress(hLibrary_, "CreateTimerQueueTimer");
    deleteTimerQueueTimer = 
     (DELETETIMERQUEUETIMER)GetProcAddress(hLibrary_, "DeleteTimerQueueTimer");

    InitializeCriticalSection(&cs_);
    hTimer_ = createTimer();
}

void
CScheduler::stop(){
    cancelTasks();
    deleteTimerQueue(hTimer_);    
    DeleteCriticalSection(&cs_);
    FreeLibrary(hLibrary_);
}

void
CScheduler::enqueueTask( int interval, void(*callback)(void) ){

    CTask* newTask = new CTask(*this, callback);    
    HANDLE hQueueTimer = 0;

        EnterCriticalSection(&cs_);
    createTimerQueueTimer(                        &hQueueTimer, hTimer_,                        (WAITORTIMERCALLBACK)WaitOrTimerCallback,                        (void*)newTask,                        interval, 0, WT_EXECUTEINPERSISTENTTHREAD | WT_EXECUTEONLYONCE );
    newTask->setHandle(hQueueTimer);
    tasks_.push_back(newTask);

       LeaveCriticalSection(&cs_);
}

void
CScheduler::cancelTasks(){

    EnterCriticalSection(&cs_);
    while(1){
        list::iterator iter = tasks_.begin();
        if(iter == tasks_.end()) break;
        iter.operator *()->finish();
    }
    LeaveCriticalSection(&cs_);
}

void
CScheduler::removeTask(CTask* task){    
    tasks_.remove(task);    
    delete task;    
}

VOID CALLBACK 
CScheduler::WaitOrTimerCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired){

    EnterCriticalSection(&CScheduler::cs_);
    CTask* task = static_cast(lpParameter);
    task->callback_();
    task->finish();
    LeaveCriticalSection(&CScheduler::cs_);
}

  

void
CTask::setHandle(HANDLE hQueueTimer){
    hQueueTimer_ = hQueueTimer;
}

void
CTask::finish(){
    sched_.deleteTimerQueueTimer(sched_.hTimer_, hQueueTimer_, NULL);
    sched_.removeTask(this);
}

这是软件的第一个版本,后续版本中可以期待以下更新... 目前,任务只能执行一次,可以使其周期性执行... 用户定义的函数参数可以缓存在 CTask 类中,并作为参数传递给回调函数。

© . All rights reserved.