I am developing an application in C# 4.0. I need to call a method depending on the current system time. Can I do it using Timer control? It would be great if someone could tell me how to do this.
Thanks,
Rakesh.
You may (and without knowing more about your app I cant say for sure) want to look at it a bit differently. You can easily write an app that sits around, doing nothing except polling what time it is, and then running whatever it is you need to do, but that will leave your application hanging around and doing nothing but taking up resources most of the time.
Instead, maybe you could consider creating a scheduled task, which will let you run your app at any given time. The Task Scheduler is documented at http://msdn.microsoft.com/en-us/library/aa383614(VS.85).aspx, and there is a managed wrapper for it at http://taskscheduler.codeplex.com/. (it says it works on XP or better, so hopefully it will cover your needs).
Good luck,
You can use the below code
System.Timers.Timer _timer1 = new System.Timers.Timer();
_timer1.Elapsed += new ElapsedEventHandler(_timer1_Elapsed);
//1 second
_timer1.Interval = 1000;
_timer1.Start();
//this event will be fired each 1 second
private void _timer1_Elapsed(object sender, ElapsedEventArgs e)
{
}
You should be able to, yes. Ghyath Serhal has told you how to use the timer class in general. The only bit missing is how to do it at a specific time. This should be pretty easy - when you set up the timer just take the time you want the action to happen and the current time, find the difference in seconds and use this to populare the interval. You'll also want to set the AutoReset property to false so that it doesn't start counting down immediately again.
If you ever change the time that the events happen you just need to hook into this with a trigger and update the timer to the new time.
Edit to add: If somebody were to change the system time that may cause problems with this plan. I'm not sure if you can easily tap into that to reset your timers. I'm guessing probably not relevant though. :)
The problem with timer is that it does not guarantee that the elapsed event would be called exactly at the right moment - all you know is that it would be called after time that is bigger than the Interval.
The solution is dependant on the resolution of the time you're interested in - for example if you need to check each minuet if a specific event occurs you can set a timer to raise the event every minuet and then use DateTime.Now to check if the system time is the time the event should occur.
A good policy is to always expect the timer elapsed event to happen several seconds after the Interval set depending on how busy the system is.
Related
I have an application in which the user is able to create different notifications, like sticky notes and set their starting times. When he presses the start button a timer starts and these reminders should pop up at the time they were set for. I've searched for other answers, like this one, but the problem here is the notifications' times are different.
So what is the best way to schedule the events that activate the notifications?
I can think of two possible ways with their Pros and Cons:
Run a DispatcherTimer, that ticks every second and checks whether the time for a notification has come and pop it up. Pros: single DispatcherTimer instance. Cons: ticking every second and checking all notifications is an overhead.
Create a DispatcherTimer for each notification and let them handle time themselves. Pros: every timer ticks just once to pop the notification. Cons: too many timers is an overhead and may be hard to control.
Am I on the right track? Which of the two approaches is better, resource wise? Is there a third better way I am overlooking?
EDIT: If it makes any difference, the notifications should also auto close after some user-defined time and repeat at regular user-defined intervals.
I've used many methods to schedule events in C# Applications (Threads, Timers, Quartz API...), and I think that the Quertz.NET API -link- is the best tool you'll find (For me at least). It's easy and simple to use.
Example of your job class:
public class HelloJob : IJob
{
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("Greetings from HelloJob!");
}
}
Example from the internet:
// Instantiate the Quartz.NET scheduler
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler();
// Instantiate the JobDetail object passing in the type of your
// class. Your class needs to implement a IJob interface
var job = new JobDetail("job1", "group1", typeof(HelloJob));
// Instantiate a trigger using the basic cron syntax.
// Example : run at 1AM every Monday - Friday.
var trigger = new CronTrigger(
"trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI");
// Add the job to the scheduler
scheduler.AddJob(job, true);
scheduler.ScheduleJob(trigger);
You'll find a helpful code example in the QuickSart guide here.
Regards.
If the notification system is going to be used inside single process, continue with single dispatcher timer. Make sure the dispatcher timer is set to the near notification. and each time a new notification is created or timer hit ,change the time to next nearest notification.
That way you can avoid processing every time.
eg: First time when somebody creates notification point timer to that time. If someone else create another notification before first hits change the timer to second. If the second time is after the first time, change the timer after dispatching the first notification call back. If its threaded you may need to work hard to get thread safety.
If notification is needed across process use windows task scheduler which already knows how to run timer and call our code on time. You may need to use some sort of IPC (WCF net.pipe, msmq etc...) to achieve notification.
I am wondering where can I find some sample code to do this in C#:
A BackGroundWorker periodically (say, 4 times per second) checking a .txt file to see it one particular string, such as "I am done." get written in the file.
Once the BackGroundWorker finds such a string exist in the .txt, it should trigger a event becoming true.
I am a newbie for C#, so some sample would be highly appreciated. Thanks a lot.
There are two basic strategies to find out if something changed. You can poll, repeatedly check if anything is different. Or you can use an event, code that runs automagically when the change occurs. Events are of course much more effective, you don't waste any time and system resources to accomplishing little to nothing. You for example never poll a button to see if the user clicked it, you use its Click event instead.
Sometimes polling is inevitable, simply because an event is not available. But there certainly is one for a change to a file, the operating system has support for it. Exposed in .NET through the FileSystemWatcher class. Strongly recommended over a Timer or a worker thread, opening and reading every line of a file to discover a "I am done" string is very expensive.
Just be careful when you try to read the file. Also a problem when you use a Timer or worker thread, but more so because FileSystemWatcher works so much better. It is pretty likely that you can't open the file yet when the Change event fires because whatever process writes the file still has a lock on it. You may well still need a Timer to try to read the file later, after it is no longer locked.
You probably just want to use Timer. A sample code is something like this
var timer = new Timer(TimerTick, null, TimeSpan.Zero, new TimeSpan(0, 0, 0, 1));
int lastMinute = 1;
void TimerTick(object state)
{
var minute = DateTime.Now.Minutes;
if (minute != lastMinute && minute % 5 == 0)
{
lastMinute = minute;
//Check the .txt file
}
}
As Thorsten Dittmar pointed out, yes you probably want to use System.Timers.Timer than System.Threading.Timer. Timers.Timer is thread-safe too.
According to one of the answers from found here
The specific difference appears to be that System.Timers.Timer is geared towards multithreaded applications and is therefore thread-safe via its SynchronizationObject property, whereas System.Threading.Timer is ironically not thread-safe out-of-the-box.
I don't believe that there is a difference between the two as it pertains to how small your intervals can be.
There is also a link for a comprehensive explanation of timers.
There is already built in functionality to do this. Try using the FileWatcher class.
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx
I have setup DispatchTimer correctly to fire every second-
OneSecondChecker = new DispatcherTimer();
OneSecondChecker.Tick += new EventHandler(OneSecondChecker_Tick);
OneSecondChecker.Interval = new TimeSpan(0, 0, 1);
OneSecondChecker.Start();
Problem: And it fires correctly for a certain period of time after which it just stops firing.
Additional Information:
Now you might ask what does it do? There is a class level (static) boolean variable that is set to true if the method OneSecondChecker_Tick() is running, and then is set to false if it is not, so that we don't have two instances of this method running at the same time even if it is set to fire every second. It is an application requirement to make sure OneSecondChecker_Tick() runs without any delay. I am also not trying to run in an infinite loop. There is a second check to see if a table value is updated to before OneSecondChecker_Tick() runs. It is that table value that "sort of" informs OneSecondChecker_Tick() to run. That table value is updated by another application.
Within the method itself I do have a call to run threads in parallel using TPL. I don't know if it has anything to do with it.
EDIT
I still haven't been able to figure this one out. It might be that the application is frozen. The task manager does not say that though. Is it possible to tell if the application is not responding from somewhere other than the task manager?
The problem is not with DispatchTimer. It wasn't even with TPL. The problem was elsewehre in the code running in an infinite loop and causing stack overflow - after which it stopped firing.
I am working on a project where I need to let the user create one (or more) timers to fire off an event.
The user is supposed to define variables such as if the timer should be active and how often the timer will fire along with some other variables of what will happen when the timer is fiering.
All these variables are stored in a dictionary (Disctionary) where the object holds all the variables the user has set and the string is the name that the user has chosen for this timer.
I then want my program to loop through this dictionary and search for all objects which has the variable t_Active set to true (this I have already achieved).
What I need help with figuring out is the follwoing:
When it detects the variable, and if it's set to true, I need the program to see if there is already a timer created for this.
If it isn't, it should create one and set the relevant parameters for the timer.
The two variables t_num and t_period should decide the interval of the timer.
t_num is an int and t_period is a string which will be set to either minutes, hours or days.
Combining t_num with 60000 (minutes), 3600000 (hours) or 86400000 should give the corrct interval.
But how would I go on about programatically create a timer for each user-defined active object?
And how do I get the program to detect wether or not a timer has already been created?
I have been searching both here and on google, but so far I haven't come across something that makes sense to me.
I am still learning C#, so what make sense to you guys may not neccessarilly make sense to me yet. :)
I hope I have explaned what I need good enough, please do ask me to clarify if you don't get me.
Edit:
Maybe I should also mention that the mentioned dictionary will also be saved to an XML file to that the user can pick up all the settings they made at any time.
Edit 2:
#hatchet I am wondering wether or not this will work.
I have tried to make it work, but are bumping in to some difficultied (because I lack the experience and don't fully understand your pseudo-code. I am getting errors, a few that I could sovle, and a few that I couldn't. (I didn't expect fully working code, don't worry)).
Also, the user should be able to modify the timer.
In the mainform, there's a few textboxes and three buttons.
The form is used to send messages.
The user can choose to manually send their message, to add the message to a timer, or to edit the timer.
When the user hits the manual button, the messages goes out to all receivers once.
If the add the message to a timer, a new subform pops up, where they are able to set the following details:
string Name (of timer)
DateTime Start_date
CheckBox Ending
DateTime End_date
NumericUpDown Seconds (minimum value of 15 minutes)
Combobox Minutes, Hours, Days
Checkbox Active
When the user adds the message to a timer, the TimerSettings gets in to the dictionary as sting,Object (my custom object cointaing all the details).
If they hit the modify button on the main form, it is thought that before the subform is opened, the program looks for the correcponding timer (the mainform has a combobox with all added timers), stops the timer and then opens the subform to let the user edit the details.
On the subform is also a delete button so that the user can delete the timer.
When adding or modifying the timer, mainform is catching it and writes the changes to the XML file and the combobox.
And here is where it should look if there's already a timer for this message and create on of there isn't, or restart the timer if there are.
I am not sure how I should make your solution work for this though.
THe procedure of sending the messages takes anything from 30 seconds to 5 minutes depending on the number of receivers (can't be more than 42 (the program is an interface to another program which doesn't allow for more than 42 receivers)).
I understand that several timers could be an issue, but I doubt that any user would need more than max 10 timers anyway, so there could be a built in limitation of, lets say, 15 timers.
This is kind of pseudo code C#, to convey the idea. I have done this same thing, but there are enough little details that are different, that pasting that code would be confusing. So off the top of my head, this semi-code will hopefully be close enough to real code to show you what I meant by my comment to your question.
Say you have a class like this
public delegate void Work();
public class TimedThing {
public int IntervalSecs;
public DateTime NextFiring;
public event Work OnWork;
}
Then you have a controller class
public class TimedGroup {
TimedThing[] things;
System.Timers.Timer timer;
public TimedGroup() {
this.timer = new System.Timers.Timer();
this.timer.AutoReset = false;
this.timer.Elapsed += TimerFired;
}
...
// some methods for adding and removing TimerThings
...
public void Start() {
this.timer.Interval = 1; // just to get things started
this.timer.Enabled = true;
}
public void Stop() {
this.timer.Enabled = false;
}
private void TimerFired(object sender, System.Timers.ElapsedEventArgs e) {
DateTime now = DateTime.Now;
// let's have timer fire at least as frequently as every 5 minutes
// if we need to have it fire sooner than that, it will get set below
DateTime next = now.AddMinutes(5);
foreach(var thing in this.things) {
if (thing.nextFiring <= now) {
var task = Task.Factory.StartNew(() => DoWork(thing));
thing.NextFiring = thing.NextFiring.AddSeconds(thing.IntervalSeconds);
// or maybe this is more appropriate
// thing.NextFiring = Now.AddSeconds(thing.IntervalSecs);
}
if (thing.NextFiring < next) next = thing.NextFiring;
}
// set the timer to fire whenever the next soonest work needs to be done
this.Timer.Interval = (next - now).TotalMilliseconds;
this.Timer.Enabled = true;
}
private void DoWork(TimedThing thing) {
thing.Work();
}
}
There are likely details though that have to be dealt with, although many of these details have to be dealt with whether you are using a timer for every thing, or a single timer for them all. For instance, what if the work for a thing normally takes 10 seconds, but occasionally it may take 60 seconds, and they have a time interval set for 45 seconds. Sometimes the next firing will want to run that work again, although the previous work started on the previous firing is still running. That may or may not be desirable, depending on what kind of work these things are doing. If it isn't desirable, you have to add some monitoring of the tasks that get spawned so you will know if you need to skip doing the work because the previous work isn't done yet. Another thing is coding a graceful winding down. When you set the timer.Enabled to false (or timer.Stop()...which is the same thing), there is a brief period of time where the timer event can still fire, even though you stopped the timer (see Why does System.Timer.Timer still fire events when Enabled is set to false?). That can make for some weird behavior/bugs.
I'm not sure how well timers will scale with that approach. It might be worth investigating other approaches to managing these events. As #hatchet just made a comment, you could have 1 timer for the next event.. with that approach, you can set up the next one when it runs.
Another possibility is using a database and a timer that runs every <small time period> which executes all actions with due time stamps.
How can I have a WinForms program do some specific thing whenever a certain time-based condition is met?
I was thinking I could do something with two threads, where one thread runs the normal program, and the other thread merely loops through checking if the time-based condition is true yet or not, and when the condition is true it signals an event.
However I am unsure of the best way to do it. Where in the program would I call the two threads? Maybe I am thinking about it all wrong?
How would you do this?
MORE INFO:
What it has to do is check the data.dat file and see when the last time it was updated was. If it was a month or more then do the specific thing. Could this still be done with a Timer?
NOTE:
I think it might be useful to note the difference between the System.Timers and the System.Windows.Forms.Timer...
I think you should use a Timer set to an inteligent interval to check if your time-based condition is met.
It depends what your time-based condition is. Is it a special time or an interval after which you want to do something special? If it's the second, you can just use the Timer and do what you have to do when the Timer.Elapsed event is fired.
Edit after your edit:
If you want an event to be fired every time the file changes, use a FileSystemWatcher
Edit2:
Here's the difference between System.Windows.Forms.Timer and System.Timers:
The Windows Forms Timer component is
single-threaded, and is limited to an
accuracy of 55 milliseconds. If you
require a multithreaded timer with
greater accuracy, use the Timer class
in the System.Timers namespace.
You could add a System.Windows.Forms.Timer control to your Form (see the Components category in the toolbox).
Then set the timer's interval to some value (e.g. 1000) and add a handler for its Tick event. This handler will then be called once every 1000 milliseconds.
In the handler you can then check if the conditions are met and if yes, start your specific operation.
Update (after you updated the question):
To check if the last modification of a file was more than one month ago, you can use this code:
if (File.GetLastWriteTime("data.dat").AddMonths(1) < DateTime.Now)
{
// do whatever has to be done
// if it is a time-consuming task, start a new thread!
}
You can still put this into the Tick event handler of the timer component. But in that case it does probably not make sense to fire the timer every second.
Depending on your application (e.g. if it will be started quite often), another possibility would be to execute the above check during the startup of your application.
Regarding your 'more info':
How many times must it check the modification-date of that specific file ?
Only once (during startup for instance), or should it check the modification-date of that file multiple times during application execution ?
If it has to be done only once, then it is useless to use a timer.
If it has to be done multiple times, then yes, you could use a timer.
The eventhandler of the Elapsed event could then check the ModificationDate of the file, and see if action needs to be taken.
Another solution, which is probably more elegant, is using a FileSystemWatcher.
This FileSystemWatcher could 'watch' that particalur file.
Specify a Filter on the FileSystemWatcher so that, every time the particular File is changed, an event is raised.
In the eventhandler of the FileSystemWatcher, you can then take the necessary action:
FileSystemWatcher dataFileWatcher = new FileSystemWatcher();
dataFileWatcher.Path = "path to your file";
dataFileWatcher.Filter = "yourfilename";
dataFileWatcher.Changed += new FileSystemEventHandler(OnFileChanged);
dataFileWatcher.NotifyFilter = NotifyFilters.LastWrite;
dataFileWatcher.EnableRaisingEvents = true;
private void OnFileChanged( object sender, FileSystemEventArgs e )
{
// take action.
}
Note however, that there's a sublte bug / feature in the FileSystemWatcher which causes that the Changed event gets raised multiple times for one change to the File you're watching.
You can resolve this like this
Another alternative, if you know the time between file updates (a month) is to check once at startup time. If the file is out of date you can process it immediately. If not, you can then work out how long you need to wait before checking it again. You can then schedule a task using a wait timer or other methods as described in the answers.
Basically, at startup time you can find out the limit/worst case on how long you have to wait and then you don't need to do any additional checks in the meantime. This assumes of course that the file can't be changed to an OLDER version during the running of the program which seems unlikely, but not impossible!