How to trigger a timer tick programmatically? - c#

Let's say I have a Windows Forms timer configured with a 10 second (10k ms) interval:
myTimer.Interval = 10000;
I want to start it and fire off the Tick event right away:
myTimer.Start();
myTimer_Tick(null, null);
The last line works but is there a better or more appropriate way?

The only thing I'd do differently is to move the actual Tick functionality into a separate method, so that you don't have to call the event directly.
myTimer.Start();
ProcessTick();
private void MyTimer_Tick(...)
{
ProcessTick();
}
private void ProcessTick()
{
...
}
Primarily, I'd do this as direct calling of events seems to me to be a Code Smell - often it indicates spagetti structure code.

There are at least 4 different "Timers" in .NET. Using System.Threading you can get one that specifically allows you to set the initial delay.
var Timer = new Timer(Timer_Elapsed, null, 0, 10000);
There are benefits to using the different timers and here is a good article discussing them all.

You could set the interval to 1 (0 probably means infinite timeout) and set it to 10k when it ticks for the first time.
The timer will tick "very soon" (depending what type of Timer you are using, see this) but the execution will not continue with the click handler as in your solution.
(I suppose you knew about the solution from Bevan).

Use two timers.
The First that has the normal interval you want to use and just enables the Second timer.
The Second timer has an interval of 100ms and is normally disabled. It runs your code and then disables itself.
To manually trigger, just enabled the Second timer.
This also allows you to trigger the code from another form using full qualification naming to the Second timer. I use this when calling from one form to another.

Related

Why Timer has no properties, how to get it's interval after initialization?

I'm using a System.Threading.Timer in my windows service for nightly import routines. It looks every minute into the database for new files to be imported. Now, since the service runs all day long, i want to change it so that it runs at night every minute and at day every 5th minute.
Therefore i thought i could check the current time, between 7am and 10PM use the day-interval-configuration value, otherwise the night-interval.
Now to the actual question: why is there no property in the Timer-class which indicates the current period/interval? Then i could decide whether i have to change it or not according to it's value.
As a workaround i could store it in an additonal field, but i wonder if it's possible to get the value from the timer itself.
Note that i'm using this constructor:
//start immediately, interval is in TimeSpan, default is every minute
importTimer = new System.Threading.Timer(
ImportTimer_Elapsed,
null,
TimeSpan.Zero,
Settings.Default.ServiceInterval_Night
);
Why is there no property in the Timer-class which indicates the current period/interval?
I assume (I'm not part of the .NET implementation team, so have to assume) this is because it used a Win32 Waitable Timer. And there is no API to get the settings of a Waitable Timer.
Note, if such properties did exit there would be a race condition:
Thread 1 reads the property and starts some business logic based on it
Thread 2 changes the property (invalidating thread 1's logic)
Thread 1 updates the property.
while any specific use of a timer may not suffer this, the general case has to cater for it.
(In Win32 this is even worse a WaitableTimer can be named, and thus accessed from other processes.)
You can use System.Timers.Timer instead, which provides such a property (".Intervall")
System.Threading.Timer does not have an internal field with the intervall value. I took a look into the .net code and i saw it isnt possible to get the current period by reflection.
Don't mess around with the tick rate. Instead invoke your code after a fixed number of ticks, depending on time:
private void ImportTimer_Elapsed(object o)
{
tickCount--;
if (tickCount <= 0)
{
// do your stuff
tickCount = Between7AMAnd10PM() ? 5 : 1;
}
}

C# program freezes using stopwatch to time an action

I have a Windows form program which controls a light. This light has its own class. I can do things like turn it on an off and change the color etc. This I can do without issue. What I want to be able to do, however, is make the light go on for a specific amount of time, i.e. 100 milliseconds or 300 milliseconds (depending on use).
I have tried to used stopwatch to do this, but when I click on the button that is meant to do this, it freezes the program. The light goes on, then doesn't turn off, and I can't use the stop button I have which is meant to turn it off.
The program loads the light, and initialises it, and displays an alert saying it has done this and detected one light. Then I use this:
private void Red_Click_1(object sender, EventArgs e)
{
//Displays Red
System.Threading.Tasks.Task.Factory.StartNew((Action)delegate()
{
displayRedDot();
});
}
This is the displayRedDot()
public void displayRedDot()
{
System.Diagnostics.Stopwatch clock1 = new System.Diagnostics.Stopwatch();
long elapsedTime = clock1.ElapsedMilliseconds;
clock1.Start();
while (elapsedTime < 100)
{
oBlynclightController.Display(BlynclightController.Color.Red);
}
oBlynclightController.Display(BlynclightController.Color.Off);
clock1.Stop();
}
I have some other functions, which are identical this with a different time, which I haven't invoked anywhere yet because I can't get this to work.
Your code will never work since you are blocking the UI thread by busy waiting. This is the reason for your program seems to freeze. Use a timer or async/await instead
async void DisplayRedDot(int duration)
{
oBlynclightController.Display(BlynclightController.Color.Red);
await Task.Delay(duration);
oBlynclightController.Display(BlynclightController.Color.Off);
}
elapsedTime will never change its value. You initialize it right after creating the stopwatch, but never assign a new value to it. Stopwatch.ElapsedMilliseconds is a long. long is a value type. A copy is created and assigned to elapsedTime. You need:
while (clock1.ElapsedMilliseconds < 100)
{
oBlynclightController.Display(BlynclightController.Color.Red);
}
Note that this loop is going to run very quickly until that check returns false. Is this really what you want? I don't know exactly what your code is doing (you don't show us), but why not just set the color to red, wait 100ms, and then set it to... erm, Off.
It's also difficult for humans to pick up a change that only lasts 100ms. It's going to be a flicker at best.

Updating Text Box

I'm writing a program to help with a game. I need it to update the text box that shows the current exp value, on the forum load it does show the exp, I need it to update the exp like every 3 seconds.
How would I go about doing that?
Here is what I have so far:
Client C = Client.GetClients()[0];
Player P;
P = C.GetPlayer();
expTextBox.Text = ("Experience: " + P.Experience.ToString());
I am not sure if I need a timer (which i have tried and I am very bad at making) or if a backGroundWorker would be best.
Based on your comments, I would recommend that you update your UI when your player/s are attacking, and not use a timer. This will keep your UI the most up-to-date and will probably serve you better than a 3 or 10 second timer. You will have a method like this:
public void Attack(Enemy e)
{
//do your attack code
//did the enemy die?
KillEnemy();
//add exp just for landing a successful attack
AddExp(e);
}
public void AddExp(Enemy e)
{
CurrentPlayer.Exp += e.ExperienceGain;
//update the UI with the new exp
GameWindow.ExperienceBox.Text = CurrentPlayer.Exp;
}
This is of course more pseudocode, because I have no idea what your design looks like, but I've made quite a few games, and this is how I always do it.
Good Luck!
I would encourage you to use Timer if you go to the background worker with infinite loop that is okay but you need to take care of two things when you use background workers:
Updating textbox or any other UI won't work as it needs to be done from the main thread. so you need to check myTextbox.requireInvoke() function before.
Check if the background worker got a cancel signal to exist the infinite loop.
on the other side. you will consume some time when you use timers to update the text box. as the timer would go to the event processing cycle in the windows then fire the event and finally you will write the code in the timer event.

WPF Multiple Timer Control

I searched a few links for Timer Control for both Windows and WPF applications but I would appreciate some advice on my situation...
As I'm using WPF it seems initial options are either System.Windows.Threading.DispatcherTimer or System.Diagnostics.Stopwatch
What I need to achieve is for each WPF DocumentPanel to request an update from an external API at a defined interval between typically 100ms Min - anytime Max with the interval unique to each DocumentPanel. Eg DP1 could be 100ms, DP2 could be 20,000ms etc.
Normally my app would start with 1 DocumentPanel but the user can expand panels without limit so it's the users judgement on CPU ability and speed of app.
Criteria include:
Multiple DocumentPanels - Typically 1 - 20 minimum but any advice on scalability is welcome.
Variable event interval (Iv) (Minimum event interval 100ms - Max < 1day)
Accuracy - 1ms (cannot have interval below (Iv)ms under ANY circumstances, over is not as much concern but needs to be be within several ms) EDIT: 1ms is not strictly a requirement but average (Iv) must be maintained over a short timescale.
Each DocumentPanel must display live date/time but produce events based on set interval
I'm really after help with design consideration rather than actual code at the moment as WPF is confusing matters for me.
Currently, I'm verging towards using a single instance of System.Diagnostics.Stopwatch and allow each panel to act on the stopwatch event whether the interval time has been reached.
Can anyone advise?
Thank you
O
its better to use just one System.Windows.Threading.DispatcherTimer with 100ms as ticks, then use Tags to determine its own interval, for example you can use
struct IntervalComparer
{
int myinterval; //the individual update interval (300ms for example)
int currentinterval;
public IntervalComparer(int myinterval)
{
this.myinterval=myinterval;
this.currentinterval=0;
}
public void TickMe()
{
currentinterval++;
}
public void ResetkMe()
{
currentinterval = 0;
}
public bool CanIUpdate()
{
return myinterval == currentinterval;
}
}
on the creation
.... Form_Loaded....
{
.....
mypanel=new Panel();
mypanel.Tag= new IntervalComparer(2); // 2 * 100ms
.....
}
.... Timer_Tick....
{
....
(mypanel.Tag as IntervalComparer).TickMe();
if((mypanel.Tag as IntervalComparer).CanIUpdate())
{
UpdateMyPanel();//your update method
(mypanel.Tag as IntervalComparer).ResetMe();
}
....
}
Generally in a case like this I would have a single timer which when then check for the elapsed time for each DocumentPanel. I'm guessing 100% accuracy is not critical, if they select 999ms then they won't notice if you main timer fires every 50ms so can only give them increments of 50ms. Windows does not give that sort of accuracy anyway, I learnt this when trying to trigger a flash once.
I've used the following approach to achieve something similar in a Silverlight app:
Single timer which ticks at a small interval (you're discretion, but would need to be lower than the lowest supported update interval), and then have each DocumentPanel subscribe to this timer's tick event.
When the tick event is fired, each DocumentPanel would then determine if an update is required based on it's update frequency (E.G. (last update - now ) > interval).
There's a comparison of some timer classes here:
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
DispatcherTimer isn't mentioned, but the important difference between DispatcherTimer and System.Timers.Timer is:
If a System.Timers.Timer is used in a WPF application, it is worth
noting that the System.Timers.Timer runs on a different thread then
the user interface (UI) thread. In order to access objects on the user
interface (UI) thread, it is necessary to post the operation onto the
Dispatcher of the user interface (UI) thread using Invoke or
BeginInvoke. Reasons for using a DispatcherTimer opposed to a
System.Timers.Timer are that the DispatcherTimer runs on the same
thread as the Dispatcher and a DispatcherPriority can be set on the
DispatcherTimer.
(from http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx).
Without knowing how you are currently handling UI updates and how you're program is structured, it's hard to say which timer you should use.
I'm not hugely familiar with the using the StopWatch, but my opinion is (after reading http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx) that using a single StopWatch isn't something that is particularly suited to this problem
use can inherit from DocumentPanel if you need the Tag property & for more encapsulation
class UpdatableDocumentPanel : DocumentPanel
{
public int myinterval { get; set; }//the individual update interval (300ms for example)
int currentinterval;
public void Update()
{
currentinterval++;
if (myinterval == currentinterval)
{
currentinterval = 0;
UpdateMyPanelMethod();
}
}
}
and
.... Form_Loaded....
{
.....
mypanel.myinterval = 2; // 2 * 100ms
.....
}
.... Timer_Tick....
{
....
mypanel.Update(); // simply
....
}

Callback with a time

I want to implement a method that callback a method at a precise time. We can have more than a method that can be called at the same time.
public void CallmeBack(DateTime time, Action callback)
{
}
What's the best implementation in C# ?
My quick and dirty solution was to create a dictionary Dictionary<DateTime, List<Action>> and to make a timer every each (minute/second) and check the time (DateTime.Now) and a current time in the test mode.
The solution have to be "Safe" if the current machine time changed. So a simple solution like this couldn't work :
Timer timer = new Timer((param) => {callback.Invoke();}, null,
(long)(time - DateTime.Now).TotalMilliseconds, Timeout.Infinite);
Edit :
Typical case where simple timer don't work is DST and manual time/date adjustment.
Plus, I just want the callback executed once not multiple times.
What you are looking for is a cron library. There are many out there. Some have a lot of features and are a bit heavy. Here is a blog post about cron jobs and a library that I have used in production code.
http://blog.bobcravens.com/2009/10/an-event-based-cron-scheduled-job-in-c/
Hope that helps get you started.
Bob
A couple of alternatives you may want to consider:
You could use a task scheduler such as :http://taskscheduler.codeplex.com/
You could stick with a timer and listen for time changes using: SystemEvents.TimeChanged. That event is triggered by user time changes. I assume you can handle predictable time changes (daylight saving etc.) when setting the timer in the first place. I'm not sure about NTP-related changes - you'd need to investigate that further.

Categories