Home>

1.Timer can only perform tasks that are separated by a period of time between tasks,As shown below

But what I need is that the time between the start of this task and the start of the next task is the same time.As shown below

In this case, the timer cannot meet the demand.

The time interval of 2.timer is generally fixed,But if i want to change the sleep time each time you execute the task, You need to call the timer's change method.

3.Timer's sleep time is not determined by the number of milliseconds of sleep through shaping,It is determined by a timespan, which is not completely convenient for tasks that are executed once a day or how many minutes per hour.

For the three above,I encapsulated the timer a bit,The timer is deprecated, or the original thread is used, and a pattern string describing the repeating time is defined.Calculate the timespan, and then call the thread's sleep () method to sleep.The class diagram of the entire component is shown below

At the bottom are two classes related to time calculation.Two agents are delegates of two task methods,The base class basecyclemission is the accumulation of periodic tasks,Implemented the icycle interface, which mainly controls the task thread (start, stop, etc.), and inherits his two subclasses. One is to implement the requirements I described in the first point aboveA function similar to the original timer. They each use different delegates.missionmanager is just a management of all periodic tasks,Unify to start or pause a certain type of task.

Time calculation module

First, let's introduce the defined string pattern.There are two modes of the cycle now encountered,

One is how often i want to perform a task,This is the most common form of cycle,Take every 5 minutes as an example,The full form is "-99--99--99 -99:05:00", "-99" is the default meaning,Of course, there are other shorthand modes;

The other is when the task is not executed once,For example, before 12 noon as an example, the complete form is "ff-ff-ff 12:ff:ff", "ff" is the default formOf course you can also use "ff", there are other shorthand patterns here.

The pattern of all strings is shown in the following table

Every time Every *** time
complete ffff-ff-ff ff:ff:ff or
ff-ff-ff ff:ff:ff
-99--99--99 -99:-99:-99
Date part ffff-ff-ff or
ff-ff-ff
-99--99--99
Time part ff:ff:ff or
ff:ff:ff
-99:-99:-99
Time abbreviation ff:ff or
ff:ff
-99:-99

The processing flow of the time calculation module is,Given the corresponding pattern string,timepointconverter uses the regular expression to match the corresponding pattern,Returns the matched year, month, day, hour, minute, and second values.After getting the result, call sleeptimeprovider to calculate how long the thread will sleep.The following shows part of the code of the two classes

public class timepointconverter
{
//other members
private int [] datetimefixbuilder (string timestr)
{
int [] result=null;
string [] dtarray=timestr.split ();
string [] datearray=dtarray [0] .split ("-");
string [] timearray=dtarray [1] .split (":");
uint year, month, date;
uint hour, minute, second;
uint.tryparse (datearray [0], out year);
uint.tryparse (datearray [1], out month);
uint.tryparse (datearray [2], out date);
uint.tryparse (timearray [0], out hour);
uint.tryparse (timearray [1], out minute);
uint.tryparse (timearray [2], out second);
//return innerfixbuilder (year, month, date, hour, minute, second);
result=new int [] {(int) year, (int) month, (int) date, (int) hour, (int) minute, (int) second);
return result;
}
//other members
}
public class sleeptimeprovider
{
//other members
public timespan innerfixbuilder (uint year, uint month, uint date, uint hour, uint minute, uint second)
{
uint [] uinttimearray=new uint [6] {year, month, date, hour, minute, second};
int [] intnowarray=new int [6]
{
datetime.now.year, datetime.now.month, datetime.now.day,datetime.now.hour, datetime.now.minute, datetime.now.second
};
int [] inttimearray=new int [6];
inttimearray [0]=uinttimearray [0] == 0?-datetime.now.year:(int) uinttimearray [0];
for (int i=1;i<uinttimearray.length;i ++)
{
inttimearray [i]=inttimearray [i-1]<0&&uinttimearray [i] == 0?
-intnowarray [i]:(int) uinttimearray [i];
}
datetime goaltime=new datetime (math.abs (inttimearray [0]),math.abs (inttimearray [1]),math.abs (inttimearray [2]),math.abs (inttimearray [3]),math.abs (inttimearray [4]),math.abs (inttimearray [5]));
if (goaltime&datetime.now)
{
int max=-1;
for (int i=inttimearray.length-1;i>= 0;i--)
{
if (inttimearray [i]<0&&i&max;max)
{
max=i;
inttimearray [i]-;
}
inttimearray [i]=math.abs (inttimearray [i]);
}
goaltime=new datetime (math.abs (inttimearray [0]),math.abs (inttimearray [1]),math.abs (inttimearray [2]),math.abs (inttimearray [3]),math.abs (inttimearray [4]),math.abs (inttimearray [5]));
}
return goaltime-datetime.now;
}
//other members
}

Thread call module

Thread calling module is the core part of task execution.missionentiy is a wrapper for thread operations,Primarily responsible for starting,Stop, pause, etc.thread uses a background thread,Make a few more judgments about thread operations.For example, the definition of suspending that operation is as follows

public bool pause ()
{
if (actionthread == null) return false;
if (actionthread.threadstate == (system.threading.threadstate.running | threadstate.background) ||
actionthread.threadstate == (system.threading.threadstate.waitsleepjoin | threadstate.background))
{
actionthread.suspend ();
return true;
}
return false;
}

cyclemission is the real task carrier,There are also operations on threads inside,But it also took some time to process,The core is the thread's buildmainaction method. This method calculates the time to sleep.Put the thread to sleep,When the time comes, the appropriate method delegate is called.

public class basecyclemission:icyclemission
{
//other members
protected void buildmainaction (string normalcycle, string overtimecycle, object overtimedelegate, bool issleepbefore, bool isinclude)
{
mainaction=() =>
{
timespan sleeptime=timespan.minvalue;
bool result=true;
timepointconvert.circletype type;
#region sleep early
if (issleepbefore)
{
type=timepointconvert.default.prasetype (normalcycle);
if (type == timepointconvert.circletype.interval)
sleeptime=sleeptimeprovider.defult.innerintervalbuilder (
timepointconvert.default.convertcircle (normalcycle));
else
sleeptime=sleeptimeprovider.defult.innerfixbuilder (
timepointconvert.default.convertcircle (normalcycle));
if (sleeptime.totalmilliseconds>0)
thread.sleep (sleeptime);
}
#endregion
while (true)
{
#region calculation time
if (isinclude)
{
if (result)
{
type=timepointconvert.default.prasetype (normalcycle);
type=timepointconvert.default.prasetype (overtimecycle);
sleeptime=type == timepointconvert.circletype.interval?
sleeptimeprovider.defult.innerintervalbuilder (
timepointconvert.default.convertcircle (overtimecycle)):
sleeptimeprovider.defult.innerfixbuilder (
timepointconvert.default.convertcircle (overtimecycle));
}
}
#endregion
#region execution method
if (overtimedelegate is overtimecycledelegate)
result=(overtimedelegate as overtimecycledelegate) .invoke ();
else
{
(overtimedelegate as cycledelegate) .invoke ();
result=true;
}
#endregion
#region calculation time
if (! isinclude)
{
if (result)
{
type=timepointconvert.default.prasetype (normalcycle);
sleeptime=type == timepointconvert.circletype.interval?
sleeptimeprovider.defult.innerintervalbuilder (
timepointconvert.default.convertcircle (normalcycle)):
sleeptimeprovider.defult.innerfixbuilder (
timepointconvert.default.convertcircle (normalcycle));
}
else
{
type=timepointconvert.default.prasetype (overtimecycle);
sleeptime=type == timepointconvert.circletype.interval?
sleeptimeprovider.defult.innerintervalbuilder (
timepointconvert.default.convertcircle (overtimecycle)):
sleeptimeprovider.defult.innerfixbuilder (
timepointconvert.default.convertcircle (overtimecycle));
}
}
#endregion
if (sleeptime.totalmilliseconds>0)
thread.sleep (sleeptime);
}
};
}
//other members
}

Of course, calling is not calling this method,The call just calls its two types of exceptcyclemission and includecyclemission, which respectively represent the two types of task execution time not included in the cycle and included in the cycle.

Manager section

Manager is mainly a dictionary collection,Is a dictionary set of icyclemission and strings,It contains operations on all elements in the collection:add, delete, run, resume, pause, stop. In addition to deletions and additions,Others include methods similar to the following

runallmission ()
runallincludecyclemission ()
runallexceptcyclemission ()
runmissionamong (params string [] missionnames)
runmissionexcept (params string [] missionnames)

But this method calls the callaction method,

private void callaction (ienumerable<icyclemission>missioncollection, action method)
{
if (missioncollection == null || method == null || missioncollection.count () == 0) return;
foreach (icyclemission item in missioncollection)
{
method.method.invoke (item, null);
}
}

For example, call the runallexceptcyclemission () method as follows

public void runallexceptcyclemission ()
{
callaction (this.values.where (c =>c is exceptcyclemission), basecyclemission.default.runmission);
}

Interested friends can test the sample code described in this article,I believe there will be no small gains!

c
  • Previous Save a piece of data to a txt file in php and display its content
  • Next Implementation method of Net framework drawing technology for Windows form