public static TaskParameter Periodic(string name, int startSec, int periodSec, Action<TaskServer, string> proc) { var param = new TaskParameter(); param.Name = name; param.StartSec = startSec; param.PeriodSec = periodSec; param.ReleaseCount = -1; param.Proc = proc; return param; }
// thread safe public void RegisterTask(TaskParameter taskParam) { Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}] Register task ({1}sec, T={2}, count={3})", taskParam.Name, taskParam.StartSec, taskParam.PeriodSec, taskParam.ReleaseCount); // to be released from release thread Action taskProc = () => { // get semaphore and do Proc() bool enter = taskSema.Wait(0); if (!enter) { // Max count tasks are running, give up Log.Trace.TraceEvent(TraceEventType.Warning, 0, "[{0}] Task count full, give up", taskParam.Name); return; } try { Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}] Start", taskParam.Name); taskParam.Proc(this, taskParam.Name); Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}] Completed successfully", taskParam.Name); } catch (OperationCanceledException) { Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}] Task cancelled", taskParam.Name); } catch (Exception e) { Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}] Exception", taskParam.Name); Log.Trace.TraceData(TraceEventType.Error, 0, e); } finally { taskSema.Release(); } }; // release thread, which releases releaseProc Task.Run(() => { try { // delay, using CencelToken Task.Delay(taskParam.StartSec * 1000).Wait(CancelToken); int count = 0; while (taskParam.ReleaseCount < 0 || count < taskParam.ReleaseCount) { // release task Task.Run(taskProc); // delay, using CencelToken Task.Delay(taskParam.PeriodSec * 1000).Wait(CancelToken); if (taskParam.ReleaseCount >= 0) { count++; } } } catch (OperationCanceledException) { Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}-release-thread] Task cancelled", taskParam.Name); } catch (Exception e) { Log.Trace.TraceEvent(TraceEventType.Information, 0, "[{0}-release-thread] Exception", taskParam.Name); Log.Trace.TraceData(TraceEventType.Error, 0, e); } }); }