 |
|
|
 |
|
|
 |
|
 |
Hi
I just try the application on VS 2008, and it does not work. After pressing 'Test Code' , at the window of Schedules View, when the Messagebox with the ScheduleCallback message appear, there is an Exception
System.InvalidOperationException was unhandled Message="Cross-thread operation not valid: Control 'SchedulesView' accessed from a thread other than the thread it was created on." Source="System.Windows.Forms" StackTrace: at System.Windows.Forms.Control.get_Handle() at System.Windows.Forms.ListView.ListViewNativeItemCollection.DisplayIndexToID(Int32 displayIndex) at System.Windows.Forms.ListView.ListViewNativeItemCollection.get_Item(Int32 displayIndex) at System.Windows.Forms.ListView.ListViewItemCollection.get_Item(Int32 index) at EventScheduler.SchedulerUI.OnSchedulerEvent(SchedulerEventType type, String scheduleName) in C:\Serraview\EventScheduler_src\EventScheduler\SchedulerUI.cs:line 616 at EventScheduler.Scheduler.DispatchEvents(Object obj) in C:\Serraview\EventScheduler_src\EventScheduler\Scheduler.cs:line 65 at System.Threading._TimerCallback.TimerCallback_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading._TimerCallback.PerformTimerCallback(Object state) InnerException:
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Hello everybody
Does anybody know how can I persist Schedule data on a database? I want to have all the schedule data on a database instead of adding them manually...
I was thinking how I could design some tables for this, but I don't have much experience... If somebody could help me would be great.
Thanks!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, thank you for showing us how you implement this component. I am now using this to implement a backup function for my application. I have made many changes to your code where for most part it is unrecognizable, most noticeably to be able to save the schedules into XML via serialization. I would like to use some of your concepts and sample code for a commercial application, is this alright with you? Thanks once again.
I love codes that just work!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Joseph, please feel free to use the idea. If you can give credit to the article in the application you are building, I will be very happy. Good luck.
Sriram Chitturi
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Has anyone had any experience of using this component in a non-gui application?
A console app or (more interestingly) a windows service?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I took the code and modified it for my service. I think customization is part of the game when we borrow code from internet :->
|
| Sign In·View Thread·PermaLink | 4.20/5 (3 votes) |
|
|
|
 |
|
 |
After using these classes in couple projects, I found tons of mistakes. Here is my version that I use (it is also not perfect, but IMHO more usefull). There are changes basically in every class:
Schedule.cs
using System; using System.Threading;
namespace EventScheduler { public delegate void Invoke(string scheduleName);
public enum ScheduleType { ONETIME, INTERVAL, DAILY, WEEKLY, MONTHLY };
abstract public class Schedule : IComparable { public event Invoke OnTrigger; protected string m_name; protected ScheduleType m_type; protected bool m_active; protected DateTime m_nextTime; protected TimeSpan m_fromTime; protected TimeSpan m_toTime;
bool[] m_workingWeekDays = new bool[]{true, true, true, true, true, true, true};
protected TimeSpan m_interval = new TimeSpan();
public void SetWorkingDaysOnly() { SetWeekDay(DayOfWeek.Monday, true); SetWeekDay(DayOfWeek.Tuesday, true); SetWeekDay(DayOfWeek.Wednesday, true); SetWeekDay(DayOfWeek.Thursday, true); SetWeekDay(DayOfWeek.Friday, true); SetWeekDay(DayOfWeek.Saturday, false); SetWeekDay(DayOfWeek.Sunday, false); }
public ScheduleType Type { get { return m_type; } }
public string Name { get { return m_name; } }
public bool Active { get { return m_active; } set { m_active = value; } }
protected bool NoFreeWeekDay() { bool check = false; for (int index=0; index<7; check = check|m_workingWeekDays[index], index++); return check; }
public void SetWeekDay(DayOfWeek day, bool On) { m_workingWeekDays[(int)day] = On; Active = true; if (NoFreeWeekDay()) Active = false; }
public bool WeekDayActive(DayOfWeek day) { return m_workingWeekDays[(int)day]; }
public DateTime NextInvokeTime { get { return m_nextTime; } }
public TimeSpan Interval { get { return m_interval; } set { if (value.TotalSeconds < 1) throw new SchedulerException("Interval cannot be less than 1 second"); m_interval = value; } }
public Schedule(string name, ScheduleType type) { m_type = type; m_name = name; m_nextTime = DateTime.Now; }
public void TriggerEvents() { CalculateNextInvokeTime(); ThreadStart ts = new ThreadStart(KickOffEvents); Thread t = new Thread(ts); t.Start(); }
private void KickOffEvents() { if (OnTrigger != null) OnTrigger(Name); }
internal abstract void CalculateNextInvokeTime();
protected bool CanInvokeOnNextWeekDay() { return m_workingWeekDays[(int)m_nextTime.DayOfWeek]; }
protected bool IsInvokeTimeInTimeRange() { if (m_fromTime < m_toTime) return (m_nextTime.TimeOfDay >= m_fromTime && m_nextTime.TimeOfDay <= m_toTime); else return (m_nextTime.TimeOfDay >= m_toTime && m_nextTime.TimeOfDay <= m_fromTime); }
public int CompareTo(object obj) { if (obj is Schedule) { return m_nextTime.CompareTo(((Schedule)obj).m_nextTime); } throw new Exception("Not a Schedule object"); } } }
Scheduler.cs
using System; using System.Threading; using System.Collections;
namespace EventScheduler { public enum SchedulerEventType { CREATED, DELETED, INVOKED };
public delegate void SchedulerEventDelegate(SchedulerEventType type, string scheduleName);
public sealed class Scheduler { static public event SchedulerEventDelegate OnSchedulerEvent;
static Schedule m_nextSchedule = null; static ArrayList m_schedulesList = new ArrayList(); static Timer m_timer = new Timer(new TimerCallback(DispatchEvents), null, Timeout.Infinite, Timeout.Infinite);
public static Schedule GetScheduleAt(int index) { if (index < 0 || index >= m_schedulesList.Count) return null; return (Schedule)m_schedulesList[index]; }
public static int Count() { return m_schedulesList.Count; }
public static Schedule GetSchedule(string scheduleName) { for (int index=0; index < m_schedulesList.Count; index++) if (((Schedule)m_schedulesList[index]).Name == scheduleName) return (Schedule)m_schedulesList[index]; return null; }
static void DispatchEvents(object obj) { if (m_nextSchedule == null) return; m_nextSchedule.TriggerEvents(); if (m_nextSchedule.Type == ScheduleType.ONETIME) { RemoveSchedule(m_nextSchedule); } else { if (OnSchedulerEvent != null) OnSchedulerEvent(SchedulerEventType.INVOKED, m_nextSchedule.Name); m_schedulesList.Sort(); SetNextEventTime(); } }
static void SetNextEventTime() { if (m_schedulesList.Count == 0) { m_timer.Change(Timeout.Infinite, Timeout.Infinite); return; } m_nextSchedule = (Schedule)m_schedulesList[0]; TimeSpan ts = m_nextSchedule.NextInvokeTime.Subtract(DateTime.Now); if (ts < TimeSpan.Zero) ts = TimeSpan.Zero; m_timer.Change((int)ts.TotalMilliseconds, Timeout.Infinite); }
public static void AddSchedule(Schedule s) { if (GetSchedule(s.Name) != null) throw new SchedulerException("Schedule with the same name already exists"); m_schedulesList.Add(s); m_schedulesList.Sort(); if (m_schedulesList[0] == s) SetNextEventTime(); if (OnSchedulerEvent != null) OnSchedulerEvent(SchedulerEventType.CREATED, s.Name); }
public static void RemoveSchedule(Schedule s) { m_schedulesList.Remove(s); SetNextEventTime(); if (OnSchedulerEvent != null) OnSchedulerEvent(SchedulerEventType.DELETED, s.Name); }
public static void RemoveAllSchedules() { while(m_schedulesList.Count > 0) { String name = ((Schedule)m_schedulesList[0]).Name; m_schedulesList.Remove((Schedule)m_schedulesList[0]); SetNextEventTime(); if(OnSchedulerEvent != null) OnSchedulerEvent(SchedulerEventType.DELETED, name); } }
public static void RemoveSchedule(string name) { RemoveSchedule(GetSchedule(name)); } } }
SchedulerExceptions.cs
using System;
namespace EventScheduler { public class SchedulerException : Exception { public SchedulerException(string msg) : base(msg) { } } }
ScheduleTypes.cs
using System;
namespace EventScheduler { public class OneTimeSchedule : Schedule { public OneTimeSchedule(String name, DateTime startTime) : base(name, ScheduleType.ONETIME) { m_nextTime = startTime; } internal override void CalculateNextInvokeTime() { m_nextTime = DateTime.MaxValue; } }
public class IntervalSchedule : Schedule { public IntervalSchedule(String name, TimeSpan TimeInterval, TimeSpan fromTime, TimeSpan toTime) : base(name, ScheduleType.INTERVAL) { if(TimeInterval.Ticks >= TimeSpan.TicksPerDay) throw new SchedulerException("TimeInterval > max ticks per day"); if(fromTime.Ticks >= TimeSpan.TicksPerDay) throw new SchedulerException("fromTime > max ticks per day"); if(toTime.Ticks >= TimeSpan.TicksPerDay) throw new SchedulerException("toTime > max ticks per day");
m_fromTime = fromTime; m_toTime = toTime; Interval = TimeInterval;
DateTime now = DateTime.Now;
DateTime start = new DateTime(now.Year, now.Month, now.Day, m_fromTime.Hours, m_fromTime.Minutes, m_fromTime.Seconds, m_fromTime.Milliseconds); DateTime end = new DateTime(now.Year, now.Month, now.Day, m_toTime.Hours, m_toTime.Minutes, m_toTime.Seconds, m_toTime.Milliseconds);
m_nextTime = start;
if(fromTime < toTime) { do { if(now <= start) break;
if(now >= end || now + TimeInterval >= end) { m_nextTime = start.AddDays(1); break; }
long ticks_from_start = now.TimeOfDay.Ticks - start.TimeOfDay.Ticks; long whole_past_ticks_intervals = ticks_from_start / TimeInterval.Ticks;
start = start.AddTicks(TimeInterval.Ticks * whole_past_ticks_intervals + TimeInterval.Ticks); } while(false); } else throw new SchedulerException("Not supported time range");
m_nextTime = start; }
internal override void CalculateNextInvokeTime() { m_nextTime = m_nextTime.AddTicks(Interval.Ticks);
if (! IsInvokeTimeInTimeRange()) { Boolean bAddDay = false; if(m_nextTime.TimeOfDay > m_toTime) bAddDay = true;
m_nextTime = new DateTime(m_nextTime.Year, m_nextTime.Month, m_nextTime.Day, m_fromTime.Hours, m_fromTime.Minutes, m_fromTime.Seconds, m_fromTime.Milliseconds); if(bAddDay) m_nextTime = m_nextTime.AddDays(1); }
while(!CanInvokeOnNextWeekDay()) m_nextTime = m_nextTime.AddDays(1); } }
public class DailySchedule : Schedule { public DailySchedule(String name, TimeSpan startTime) : base(name, ScheduleType.DAILY) { if(startTime.Ticks >= TimeSpan.TicksPerDay) throw new SchedulerException("startTime > max ticks per day");
DateTime current = DateTime.Now;
DateTime today_start = new DateTime(current.Year, current.Month, current.Day, startTime.Hours, startTime.Minutes, startTime.Seconds, startTime.Milliseconds);
int res = DateTime.Compare(current, today_start); if(res > 0) today_start = today_start.AddDays(1);
m_nextTime = today_start; }
internal override void CalculateNextInvokeTime() { m_nextTime = m_nextTime.AddDays(1);
while(!CanInvokeOnNextWeekDay()) m_nextTime = m_nextTime.AddDays(1); } }
public class WeeklySchedule : Schedule { public WeeklySchedule(String name, DateTime startTime) : base(name, ScheduleType.WEEKLY) { m_nextTime = startTime; }
public WeeklySchedule(String name, DayOfWeek day, TimeSpan time) : base(name, ScheduleType.WEEKLY) { DateTime now = DateTime.Now; DateTime this_week = now.Date.AddDays(-(int)now.DayOfWeek);
m_nextTime = this_week.Add(time);
if(m_nextTime <= DateTime.Now) CalculateNextInvokeTime(); } internal override void CalculateNextInvokeTime() { m_nextTime = m_nextTime.AddDays(7); } }
public class MonthlySchedule : Schedule { public MonthlySchedule(String name, DateTime startTime) : base(name, ScheduleType.MONTHLY) { m_nextTime = startTime; } public MonthlySchedule(String name, TimeSpan startDateTimeFromTheBeginningOfTheMonth) : base(name, ScheduleType.MONTHLY) { DateTime now = DateTime.Now;
DateTime dt = new DateTime(now.Year, now.Month, 1) + startDateTimeFromTheBeginningOfTheMonth;
dt = dt.AddDays(-1);
if(dt < now) dt = dt.AddMonths(1);
m_nextTime = dt; } internal override void CalculateNextInvokeTime() { m_nextTime = m_nextTime.AddMonths(1); } } }
Dima http://www.mmexplorer.com[^]
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Dear Dima. Maybe you can find some times for update all code, because after yours updates, examples in archive EventScheduler_src.zip compiled with some errors.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
yeah, examples might not be fully compatible, because I did several changes that I needed for my projects. If you have any questions how to use the code, do not hesitate and ask me 
Dima www.mmexplorer.com[^]
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Your code almost works with one schedule.
I believe you need locks for ADD and REMOVE and anything else that plays with the schedules beyond that
Perhaps use:
lock (m_schedulesList) {
}
From a coding perspective, there appears to be a mishmash of fields and properties used. Better to go with Properties.
Some of your limits are quite arbitrary - it's not hard to make it work with no start delay and an interval of 1 second.
I think your Daily crashes if the time to run has already passed for the day you try to Add it.
I don't mind the events running on a thread but perhaps it could be an option in the Add so that short, frequent events could run on the timer's own thread. Perhaps a try/catch around the call to the delegate would help keep things alive.
"If your world is free, someone will take it away."
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Scehdules set on an interval I find don't actually expire and reschedule to the next day. Notice the code segment.
Original:
internal override void CalculateNextInvokeTime() { m_nextTime = m_nextTime.AddSeconds(Interval);
if (! IsInvokeTimeInTimeRange()) { if (m_nextTime.TimeOfDay < m_fromTime) m_nextTime.AddSeconds(m_fromTime.Seconds - m_nextTime.TimeOfDay.Seconds); else m_nextTime.AddSeconds((24 * 3600) - m_nextTime.TimeOfDay.Seconds + m_fromTime.Seconds); }
while (! CanInvokeOnNextWeekDay()) m_nextTime = m_nextTime.AddDays(1); } }
This is my version of the routine that sets the next invoke time:
internal override void CalculateNextInvokeTime() { m_nextTime = m_nextTime.AddSeconds(Interval);
if (! IsInvokeTimeInTimeRange()) { if (m_nextTime.TimeOfDay < m_fromTime) m_nextTime = m_nextTime.AddSeconds(m_fromTime.Seconds - m_nextTime.TimeOfDay.Seconds); else m_nextTime = new DateTime(m_nextTime.Year,m_nextTime.Month,m_nextTime.AddDays(1).Day,m_fromTime.Hours,m_fromTime.Minutes,m_fromTime.Seconds,m_fromTime.Milliseconds); }
while (! CanInvokeOnNextWeekDay()) m_nextTime = m_nextTime.AddDays(1); } }
Did you notice something in the original version? Every developer makes this mistake at some point. When using the "add..." functions on a variable, it doesn't actually manipulate the variable itself, instead, it returns another variable with it's added changes. Seeing this inclines me to think this source hasn't been tested entirely, which is fine, that is why I am writing this message \=)
Happy coding!
Kurios
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Goto this page and get this great tool to help ypu learn how others doit!!!
http://www.aisto.com/roeder/dotnet/
Dissasembler called : .NET Reflector.....
TRIDEX ======
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
 |
i have many tasks to execute,and every task takes much time.if I use this,it will produce many threads ,so the memory is very high.how to resolve it?
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
 |
Thanks Sriram for an excellent article; very well-written and complete in all respects. Please allow me to use the scheduler in my applications.
Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I am using event scheduler in one program i have made. I declare one time schedule event and when it finishes after some time i reschedule it with the same name again and i am repead this. On the devlopment machine its working fine, if i install this program on another machine its working for a couple of times and then it is not firing the event. this is the line of code Schedule s = new OneTimeSchedule("Stop" + rwPreview[0]["ID"].ToString(), DateTime.Now.AddSeconds(sec)); s.OnTrigger += new EventScheduler.Invoke(ScheduleCallBackStop); Scheduler.AddSchedule(s);
What i am i doing wrong?
Thank you
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
 |
If I have params which I would like to pass into ScheduleCallBack function, how could I do it with this component?
Any help will be much appreciated!
-Hanna
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
 |
Have u found a solution to ure problem because i'm having the same problem? Plz I'll be thankfull for any help
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
 |