In relation to a previous question of mine ([question] : Which thread will timer method run in? ), I've added a Timer to my Windows Forms app to run every 100ms to show how long the program session has been running. I've defined it as follows (these are only the snippets relevant to the timer):
private System.Timers.Timer timerPureTime = new System.Timers.Timer(100);
timerPureTime.Elapsed += new System.Timers.ElapsedEventHandler(updateTimeElapsed);
this.timerPureTime.SynchronizingObject = currentForm; //where currentForm is my main Form
public void updateTimeElapsed(object sender, ElapsedEventArgs e)
{
if (currentForm.lblTimeElapsed.InvokeRequired) //lblTimeElapsed is your standard Windows Form label
{
currentForm.lblTimeElapsed.Invoke((MethodInvoker)delegate //also, trying to make make GUI invoking thread-safe here
{
TimeSpan t = TimeSpan.FromSeconds(purelyTime);
string showTime = string.Format("{0:D2} min {1:D2} sec",
t.Minutes,
t.Seconds);
currentForm.lblTimeElapsed.Text = showTime;
});
}
else
{
TimeSpan t = TimeSpan.FromSeconds(purelyTime);
string showTime = string.Format("{0:D2} min {1:D2} sec",
t.Minutes,
t.Seconds);
currentForm.lblTimeElapsed.Text = showTime;
}
purelyTime += 0.1;
}
As I understand it the Timer should be running in a thread of its own (taken from the Threadpool) however it still experiences some delay every now and then, throwing the timer off-course. Other threads within the application run pretty regularly (every 250ms) and computation-intensive, but shouldn't these be independent of Timer threads?
What could be the possible causes for timer lag in such cases?
Windows cannot guarantee a precisely regular callback for a timer, so you will definitely see that kind of variance.
You need to take a different approach:
Initialise a Stopwatch field in your class.
Call Stopwatch.Restart() when you want to reset the timing.
Inside updateTimeElapsed() use Stopwatch.Elapsed instead of purelyTime.
Note that your code is completely ignoring the amount of time spent in the timer handler function itself. Inside the handler, you are using Invoke to send a message to the UI and waiting for it to return. That can take an arbitrary amount of time, particularly if the UI is busy.
Related
How to schedule the event, for instance I need to call a method which should perform its action for every given seconds. I'm developing simple windows form app, I tried using like
while(true)
{
methodToBeScheduled();
Thread.Sleep(60000);
}
This particular piece of code makes my application "Not-responding" while its executing. I hope timer can do this or any other logic that you experts suggest, kindly please let me know.
Thanks!
You can use the WinForms timer:
Timer _timer;
// In constructor (or anywhere you want to start the timer, e.g. a button event):
_timer = new Timer();
_timer.Interval = 60000; // milliseconds
_timer.Tick += (sender, e) => methodToBeScheduled();
_timer.Start();
This will cause methodToBeScheduled to be called once every 60 seconds, roughly. It will be called on the main UI thread, so avoid doing any heavy processing in it.
The advantage of using this timer is that it's built-in, doesn't require thread synchronization, and is simple to use. The disadvantage is that the interval is not exact -- the actual interval will vary depending on what other messages need to be processed in the application, and is also at the mercy of the Windows system clock, which is only accurate to 10-20ms or so.
You can use a Timer(System.Threading.Timer).
using System;
using System.Threading;
Timer _timer = null;
_timer = new Timer(o =>
{
methodToBeScheduled();
});
_timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(60));
Var sequence = Observable.interval(1).publish
Sequence.subscribe ....
Will allow to subscribe to an observable that will fire an onnext every second. See reactive extension ..
Hate typing on iPads....
Yes, there are three different types of timers (all of which are named Timer but behave a little different) in .net. The windows.forms timer executes a function at a certain rate--it calls the function from the UI thread. The System.Threading Timer does the same but calls the function from another thread. There is another timer that I can't remember off the top of my head. You will have to pick one of them based on your circumstance.
Threading timer is my favorite. Here is an example if how to use it. Just keep in mind whatever you are calling is not done from the UI thread. May want to use the forms timer or synchronize things if that's an issue.
I'm really struggling with this. I'm creating a winforms application in visual studio and need a background timer that ticks once every half hour - the purpose of this is to pull down updates from a server.
I have tried a couple of different approaches but they have failed, either due to poor tutorial/examples, or to my own shortcomings in C#. I think it would be a waste of time to show you what I have tried so far as it seems what I tried was pretty far off the mark.
Does anyone know of a clear and simple way of implementing an asynchronous background timer that is easily understandable by a C# newbie?
// Create a 30 min timer
timer = new System.Timers.Timer(1800000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
...
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// do stuff
}
with the usual caveats of: timer won't be hugely accurate and might need to GC.KeepAlive(timer)
See also: Why does a System.Timers.Timer survive GC but not System.Threading.Timer?
Declare member variable in your form:
System.Timers.Timer theTimer;
On form load (or whatever other time you need to start update polling), do:
theTimer = new System.Timers.Timer(1800000);
theTimer.Elapsed += PollUpdates;
theTimer.Start();
Declare your PollUpdates member function like this:
private void PollUpdates(object sender, EventArgs e)
{
}
I think you need to know about all timer classes. See Jon's answer below.
What kind of timer are you using?
System.Windows.Forms.Timer will execute in the UI thread
System.Timers.Timer executes in a thread-pool thread unless you
specify a SynchronizingObject
System.Threading.Timer executes its callback in a thread-pool thread
In all cases, the timer itself will be asynchronous - it won't "take up" a thread until it fires.
Source: Do .NET Timers Run Asynchronously?
I have an existing application with 1 thread running some intensive work in the background every numOfMinutesInterval. This was previously done using Thread.Sleep (sleeping for the entire interval period) but I've read that Thread.Sleep is evil and it's sloppy design, so I wanna change to a signalling mechanism. Below is the code I just wrote (using dispatcher timer from wpf, but I think in this small scenario it's the same for winforms timer as well).
The dispatcher (running in the UI thread) ticks every second, and inside the tick function it checks whether interval has passed, and if so, it will signal the manualresetevent Set(). I'm wondering if this is bad design if the intensive work extends pass the interval period? If I set the numOfMinutesInterval = 1, but the work took 1 minute and 1 second, does that mean we'll skip 1 set() call, since the tick is attempting to set() the event while work is still being done and the worker thread is not yet blocking.
Please notice also that I've set lastWorkDoneTime = DateTime.Now; after calling Set(), should I move it to the worker thread instead (calling lastWorkDoneTime = DateTime.Now; just before manualResetEvent.WaitOne();)?
If this is bad design, what should I do to change it? Thanks for reading!
//thread work done here
private void MyDoWork_ThreadStart()
{
while(FlagApplicationStillRunning == true)
{
//do the intensive work here
manualResetEvent.WaitOne();
}
}
// tick every second
private int numOfMinutesInterval = 1;
private DateTime lastWorkDoneTime = DateTime.Now;
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if((DateTime.Now - lastWorkDoneTime).Minutes > numOfMinutesInterval)
{
manualResetEvent.Set();
lastWorkDoneTime = DateTime.Now;
}
}
You could just start a task and have that perform the intensive work.
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if ((DateTime.Now - lastWorkDoneTime).Minutes > numOfMinutesInterval)
{
Task.Factory.StartNew(DoIntensiveWork());
lastWorkDoneTime = DateTime.Now;
}
}
As far as setting the lastWorkDoneTime that is up to you. If you set it in what fires off the task, you have the possibility of two or more tasks running at the same time performing the work. If you set it at the end of the function performing the work you introduce a delay that is based on how long it takes to complete the work.
I would actually look into using one of the timer objects and let that handle the timing for you instead of using the DispatcherTimer_Tick event. There is System.Timers.Timer, System.Threading.Timers, and others.
To help determine what timer option would work best for you:
Comparing the Timer Classes in the .NET Framework Class Library
I'm writing a windows service to execute some method every x minutes, but I want the method to execute synchronously relative to the timer itself. The windows service have a Timer object (System.Timers.Timer) which starts and calls some method 'DoWork' every x minutes, but the timer must 'stop' while 'DoWork' is executing and starts again after the method is finished.
I'm aware that using the System.Windows.Forms.Timer class would give me the behavior I want, but I don't want to add a System.Windows.Forms dll reference to my Service project.
Here is an example of 'working' code:
private System.Timers.Timer timer1;
public void MainMethod()
{
timer1 = new System.Timers.Timer();
timer1.Interval = 1000;
timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
timer1.Start();
}
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
timer1.Stop();
DoWork();
timer1.Start();
}
private void DoWork()
{
Thread.Sleep(2000);
Console.WriteLine("found!");
}
Running above in a console application (as a mockup before writing the windows service), the expected behavior should be for the console to write 'found!' every 3 seconds.
Just a side-note: I'm just using 'Thread.Sleep(2000)' to mimic a delay but it won't form part of the actual code base.
Is there any other / "better" way to achieve this than my way above?
Thanks for reading my question and any input would be greatly appreciated.
You can't use System.Forms.Timer in a windows service because that would require a message pump and Windows services are not given a message pump stack that can be very large (plus you'd have to call Application.Run to start one).
The way you have it now is the way I implement periodic events. I'd add something to monitor whether your events take longer than the period; but other than that...
I think it depends on whether you just want the X second delay between calls to the method to be a constant, or if you'd like the method to be called every X seconds, but with allowances if the method takes longer than X seconds to execute.
Your code above will do the former, where there's a one second delay between method calls, but if you want your method to be called every X seconds, you may want to consider using timestamps with DateTime.Now and DateTime.Subtract to see if a suitable time has passed since the last method call. This may cause unusual behaviour if the system clock gets changed, such as at daylight saving time where the method may not run for an hour but this unusual behaviour may be deemed acceptable to you in your situation.
It seems that the main problem you are having is described as " the timer must 'stop' while 'DoWork' is executing and starts again after the method is finished" .In short, the service needs to be multi-threaded. You should consider using a thread pool. Using a thread pool will allow your executing thread to continue counting time will a background thread does some other work. Check out the ThreadPool docs here: http://msdn.microsoft.com/en-us/library/3dasc8as%28v=vs.80%29.aspx .
My WPF application involves several timers. Everything works with DispatcherTimers but the delays are huge and freezes occur often (for example 3 sec freeze then the remaining 3 sec get added at once).
My problem is i am not sure how exactly i have to redesign my application to get around this problem. Never worked with threads before and its my first real WPF application as well.
I get the following error:
The calling thread must be STA, because many UI components require this.
I got this error by replacing my Dispatcher timer by a Timer from the namespace System.Timers
Old code with dispatcher timer:
timerW = new DispatcherTimer();
timerW.Tick += new EventHandler(timerW_Tick);
timerW.Interval = new TimeSpan(0, 0, 5000);
timerW.Start();
New code with Timer:
timerW = new Timer();
timerW.Elapsed += new ElapsedEventHandler(timerW_Tick);
timerW.Interval = 5000;
timerW.Start();
A query gets executed every 5 seconds to retreieve a date value. When certain conditions are met buttons get dynamically created. For example if the date remains the same for 3 min a button gets created.
Dynamic created button contains:
Date from the database
A timer that starts running when the buttons gets created. This timer only stops when a new button gets created, this records the downtime.
A reason for the downtime
The buttons get saved in a ObservableCollection and use Dependency Properties so they get notified when something changes. It is a custom button with several textblocks to display the information.
The button part is where all the interaction is at in my program, the rest of the interface just displays information fro the database. The buttons get placed in a custom made slider like control with left and right navigation buttons.
So in short my program has 3 different dispatcher timers.
One to display the current time (hh:mm:ss format)
One to execute a sql query and retrieve a date value every 5 sec
One to update the downtime timer every second inside a dynamically custom styled WPF button. I use a stopwatch to record the downtime in between.
So it seems i need to work with treads and/or backgroundworker?
Not sure how i actually begin with this since i am pretty clue less for some time now. Some example code would be most welcome.
Tldr:
I use timers for the following reasons:
Display the current time
Record downtime (real time, so i actually see it counting by the second)
A SQL query that gets executed every 5 seconds.
EDIT:
public void InitializeDispatcherTimerW()
{
TimerCallback callback = MyTimerCallBack;
timerWegingen = new Timer(callback, null, 0, 5000);
timerWegingen.Change(0, 5000);
}
private void MyTimerCallBack(object state)
{
DisplayWegingInfo();
CaculateTimeBetweenWegingen();
}
Best regards,
Jackz.
System.Timers.Timer seems to require an STA thread. An STA thread was a requirement for Windows Forms, but WPF apparently doesn't need it.
Does System.Threading.Timer meet your need?
Here is an example:
// firstTickInterval and interval are TimeSpans
TimerCallback callback = MyTimerCallback;
Timer timer = new Timer(callback, null, firstTickInterval, interval);
// timer is now running
// To stop the timer, do timer.Change(-1, -1);
The callback function would look like this:
void MyTimerCallback(object state)
{
// This is not guaranteed to execute on the UI thread.
// In this example, state will be null, since we passed null in the Timer constructor.
}
When timers callback code interact with UI elements You need to use:
UIElement.Dispatcher.BeginInvoke(...);
More info: http://msdn.microsoft.com/en-us/magazine/cc163328.aspx