Reputation: 3
I have a program that executes two timer, one for Daily and another one runs per Minute. For every elapsed time, it creates a new record to the database depending on its type. It gives smooth record on my 1st and 2nd day of continues recording but after several executions maybe after 3rd or 4th day, it saves record with duplicate entry.
Note: It only happens for the Daily timer.
ID | Message | DateCreated
1001 | Daily | 2017-01-12 03:01:01
2402 | Daily | 2017-01-13 03:01:02
2503 | Daily | 2017-01-14 03:01:03
3702 | Daily | 2017-01-14 03:01:04
3502 | Daily | 2017-01-15 03:01:04
4520 | Daily | 2017-01-15 01:01:05
5540 | Daily | 2017-01-15 03:01:05
7520 | Daily | 2017-01-15 03:01:05
What could be the possible cause? is it possible that some instance of timer is being created along the way?
class Program {
static void Main(string[] args) {
List<TimerClass> timerList = new List<TimerClass>();
timerList.Add(new TimerClass() {ID = 1, Type = "Minute"});
timerList.Add(new TimerClass() {ID = 2, Type = "Daily"});
Execute();
}
//Method to execute all default timers
static void Execute(){
foreach(TimerClass x in timerList){
x.Timer = new System.Timers.Timer();
x._exec = new ExecTimer(Save);
switch(x.Type){
case "Minute":
x.Timer.Interval = 60000;
break;
case "Daily";
x.Timer.Interval = 86400000;
break;
}
x.Timer.Start();
}
}
//method for creating record
public void Save(int id){
TimerClass i = timerList.Where(x => x.ID === id);
double interval = i.Timer.Interval;
i.Timer.Stop();
i.Timer.Dispose();
DB.Insert(x.Type, DateTime.Now.ToString());
Console.WriteLine("Successfuly Saved");
//recreate Timer
i.Timer = new System.Timers.Timer();
i._exec = new ExecTimer(Save);
i.Timer.Interval = interval;
i.Timer.Start();
}
}
//delegate for timer execution
public delegate void ExecTimer(int id);
//Timer Class
public class TimerClass{
public System.Timers.Timer Timer { get; set; }
public int ID { get; set; }
public string Type {get; set;}
public ExecTimer _exec;
public void _timer_Elapsed(object sender, ElapsedEventArgs e){
_exec(ID);
}
}
UPDATE: Corrected - Daily interval.
Upvotes: 0
Views: 1150
Reputation: 177
The "old" timer you destroy when Save
is called may have already scheduled its next execution.
As you create a new timer each time, you'll end up with the old one still being running in the background + the new one.
See https://stackoverflow.com/a/18280560/3439544 for more info on this.
One easy way over it is to stop creating a new timer each time Save
is called. Instead, set x.Timer.AutoReset
to false
when you create it. Don't stop/destroy it anymore and keep starting it after the DB call.
class Program {
static void Main(string[] args) {
List<TimerClass> timerList = new List<TimerClass>();
timerList.Add(new TimerClass() {ID = 1, Type = "Minute"});
timerList.Add(new TimerClass() {ID = 2, Type = "Daily"});
Execute();
}
//Method to execute all default timers
static void Execute(){
foreach(TimerClass x in timerList){
x.Timer = new System.Timers.Timer();
x.Timer.AutoReset = false;
x._exec = new ExecTimer(Save);
switch(x.Type){
case "Minute":
x.Timer.Interval = 60000;
case "Daily";
x.Timer.Interval = 360000;
}
x.Timer.Start();
}
}
//method for creating record
public void Save(int id){
TimerClass i = timerList.Where(x => x.ID === id);
DB.Insert(x.Type, DateTime.Now.ToString());
Console.WriteLine("Successfuly Saved");
// Re-start the timer
i.Timer.Start();
}
}
//delegate for timer execution
public delegate void ExecTimer(int id);
//Timer Class
public class TimerClass{
public System.Timers.Timer Timer { get; set; }
public int ID { get; set; }
public string Type {get; set;}
public ExecTimer _exec;
public void _timer_Elapsed(object sender, ElapsedEventArgs e){
_exec(ID);
}
}
Upvotes: 2