Why is a DispatcherTimer Tick event not occurring on time? - c#

I want to disable a button -to prevent double click: On a tablet PC you push once, it clicked twice and this is the easiest hack that I know- for a short period but I noticed/debugged the interval might be too long in practice; 50 ms vs > 2 seconds.
There is in only one line starts the timer and one line stops it. Randomly the interval is 50 ms or much bigger. There is no CPU consume, I just click the button with mouse on my 4 core desktop PC.
What would be the reason?
DispatcherTimer timerTouchDelay = new DispatcherTimer();
protected override void OnMouseDown(MouseButtonEventArgs e)
{
//Init
if (timerTouchDelay.Interval.Milliseconds == 0)
{
timerTouchDelay.Tick += new EventHandler(timerTouchDelay_Tick);
timerTouchDelay.Interval = new TimeSpan(0, 0, 0, 0, 50); //ms
}
if(timerTouchDelay.IsEnabled)
return;
timerTouchDelay.Start();
HandleKeyDown();
base.OnMouseDown(e);
}
private void timerTouchDelay_Tick(object sender, EventArgs e)
{
timerTouchDelay.Stop();
}

To understand why this is the case, I would highly recommend the following article:
Comparing the Timer Classes in the .NET Framework Class Library
For reference, DispatcherTimer is very similar to System.Windows.Forms.Timer, for which the author states "If you're looking for a metronome, you've come to the wrong place". This timer is not designed to 'tick' at exact intervals.

Instead of running a timer, why not just record the time at which the button was last pressed. If it's more than 50 milliseconds ago, go ahead and perform the action, otherwise just exit.
DateTime lastMouseDown = DateTime.MinValue;
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if(DateTime.Now.Subtract(lastMouseDown).TotalMilliseconds < 50)
return;
lastMouseDown = DateTime.Now;
HandleKeyDown();
base.OnMouseDown(e);
}

Related

How to continually update a label with the current time?

I used the following line of code
int pp = DateTime.Now.Hour;
and it is ok. I wrote
label1.text=pp.tostring();
for verification and it works, but if I open my form at 19:59 (eg.) in label1 appears 19 and after one minute, when the clock is 08:00, the value in label1 is not changing and still appears 19, not 20.
After that, if I close the form and reopen it, the number in label1 is 20.
How can I modify the value from datetime.now.hour in real time, while the form is running?
thank you
Since you are using the "form" terminology, I'll assume Windows Forms, and the easiest way would be adding a Timer component, set a reasonable Interval (reasonable meaning how long is it the maximum you can afford to delay when the hour changes before the label changes... the higher the interval, the less CPU your process will occupy) on it, and on its Tick event, do your:
static void MyTimer_Tick(object sender, EventArgs e)
{
int pp = DateTime.Now.Hour;
label1.text=pp.tostring();
}
You need to implement a Timer, and have its Elapsed event update label1.text. Simply calling DateTime.Now.Hour is not enough, as that only updates it once. It does not set a recurring method to constantly update.
using System.Timers;
namespace Example {
static Timer _timer;
static void Main() {
_timer = new Timer(1000); // Update every 1 second.
_timer.Elapsed += UpdateMyLabel;
_timer.Start();
}
static void UpdateMyLabel(object sender, ElapsedEventArgs e) {
label1.Text = DateTime.Now.Hour;
}
}
I would deduce the Label class and use timer tick for updating the label. Just like in OOP ;)

How to make DispatcherTimer show time in a textbox and perform action when reaches a certain time in C#?

This is my second question on StackOverflow here. I posted my first question a while ago and got a working reply in no time, much impressed, much appreciated.
Anyways, so what I want to know is, how to get a DispatcherTimer to work and show time in a certain textbox and stop it when it reaches a certain time (let's say 60 seconds) and perform a function after 60 seconds.
What I'm basically using this for is :
Making a game, which has to stop after 60 seconds and show the scores or related stuff. So this requires me to show the time in a textbox and perform a function at 60 seconds or after that.
Here's more information :
Textbox is called "timerbox"
Here's the code I've tried :
DispatcherTimer dt = new DispatcherTimer();
private void TimerStart(object sender, RoutedEventArgs e)
{
dt.Interval = TimeSpan.FromSeconds(1);
dt.Tick += dt_Tick;
dt.Start();
}
int count = 0;
void dt_Tick(object sender, object e)
{
count = count + 1;
timerbox.Text = Convert.ToString(count);
}
It doesn't show the time in textbox, plus I don't know how to make it stop at certain point and perform a function.
Thank you for reaching here, please leave answers with full explanation as I'm a complete beginner :)
P.S. I'm using Windows Store App Development Environment in Visual Studio 2013.
And there's no "Timer" in it as there is in normal C# Environment.
AOA.
I am recently started learning c#. (interested in windows form application). Hope this help you.
if you just want to set timer for a curtain event.....
recommend you using timer ( in toolbox )......
follow steps, when you double click on timer1 VS will create a timer1_Tick function for you which will be called every timer you timer ticks.....
now what you want to do when timer1 icks write it in there....like this....
private void timer1_Tick(object sender, EventArgs e)
{
//enter your code here
}
now write timer1. and VS will display a list of avaliable function....
for example,
timer1.Interval = (60*1000); //enter time in milliseconds
now when you want to start the write......
timer1.Start();
and to stop timer at any timer call
timer1.Stop();
if you want to repeat timer just write timer1.start() in that tick function.....
plus, to set textbox text equal to timer1 time use something like
textBox1.Text = Convert.ToString(timer1.Interval);
Click here for more information on timer class
hope this help you,
in case of any confusion, just comment,.....
The normal flow of a DispatcherTimer would look like this:
First Set up your new Object, set up the a new EventHandler that will run your desired code each Tick and Set the Timespan for the desired Tick Interval.
public MainPage()
{
this.InitializeComponent();
timer = new DispatcherTimer();
timer.Tick += new EventHandler<object>(timer_Tick);
timer.Interval = TimeSpan.FromMilliseconds(bpm);
}
Set The Timer_Tick Envent
async Void timer_Tick(object Sender, object e)
{
await this.Dispatcher.RunAsync(Windows.UI.core.CoreDispatcherPriority.High, () =>
{
//Run the Code
textBox1.text = timer.interval.TotalMilliseconds.ToString();
});
You have to have a trigger to Start the Dispatcher(and to stop if you need to), for example a button
private void StartButton_Click()
{
timer.Start();
}
This example was done using The new windows 10 Universal App platform within VS2015, but I think it should look about the same in a normal windows 8 App

Delayed countdown in DispatcherTimer

I have an app which uses DispatcherTimer to manage time, countdown things etc. and I do have multiple counters turned on while app is open. But the time is a little bit delayed, I'd say about 3-5 seconds per minute. This is part of the code I'm using:
DispatcherTimer ob = new DispatcherTimer();
ob.Interval = new TimeSpan(0, 0, 1);
private void bob_Click(object sender, RoutedEventArgs e) //Button starting countdown
{
ob.Start();
tikOb = 140;
ob.Tick += new EventHandler(ob_Tick);
}
void ob_Tick(object sender, EventArgs e)
{
tob.Text = tikOb.ToString();
if (tikOb > 0)
{
tikOb--;
}
else
{
ob.Stop();
tob.Text = "STOPPED";
ob.Tick -= new EventHandler(ob_Tick);
}
//Between these there is a code which is irrelevant in this case.
private void stopob_Click(object sender, RoutedEventArgs e) //Button breaking countdown
{
ob.Tick -= new EventHandler(ob_Tick);
ob.Stop();
tob.Text = "ON";
{
Can anyone tell me why is this happening? Did I do anything wrong inside the code? Oh, I also have another one in the code which uses different variables etc. It's completely separated. Thanks in advance!
The DispatcherTimer is executed on the UI thread. If the UI thread is currently busy doing other work for more than the interval, it will delay the execution of the Timer event and invoke it once it is free of prior work. If you need more precise scheduling, you should go for a time than runs in the background, like System.Threading.Timer or Task.Delay which can be awaited, if you're using .NET 4.5 and above. If you use the Timer and then invoke UI thread logic, you will have to remember to marshal back work to the UI thread.

What event is responsible for actions when time is out in Timer Control?

My program is some kind of test. The time of passing test is limited(20 minutes). When the time is out, the test must be finished and MessageBox appears with results of test. In Form_Load :
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = (1000) * (1);
timer1.Enabled = true;
timer1.Start();
private void timer1_Tick(object sender, EventArgs e)
{
timer_label.Text = Convert.ToString(time);
--time;
}
How to finish test when time == 0? And why time in timer_label changes with step 2?(e.g. 1999, 1997, 1995...)
How to finish test when time == 0?
Timer just raises even on some interval. You should start timer for that. If you don't want events to be raised anymore, you should stop timer. You can do it directly in Tick event handler:
private void timer1_Tick(object sender, EventArgs e)
{
timer_label.Text = Convert.ToString(time);
time--;
if (time == 0)
timer1.Stop();
}
Second question:
And why time in timer_label changes with step 2?(e.g. 1999, 1997,
1995...)
From your code there is no reason for such behavior. Looks like you have subscribed to two timers, or you have two event handlers of same timer Tick event. Also make sure you don't have decrement operator when displaying time, something like this:
timer_label.Text = Convert.ToString(--time);
--time;

C# Timer not resetting from one click to another

I need to store the piano duration with Ticks as so then make the music note show according to that duration (Music players would know).
I'm using an interval of 100, but for some testing I used it at 1000.
The problem is this. When I'm invoking the method (I'm taking the 1000 millisecond interval one) the timer starts.. if I DO NOT manage to get the 1000 milliseconds it shows Duration 0: but then if I do for example 2 seconds, it shows 3 seconds, if I try to press it for another second (a different key) it would show 4 seconds instead of 1.
It's like it keeps on recurring. Same happened with the 100 interval one. It went mad. sometimes 40 sometimes 23 and so on. Any idea how to fix (resetting the timer)
N.B I'm using System.Windows.Forms.Timer as library
part of a method which invokes the methods further below
for (int i = 0; i < 15; i++)
{
WhiteKey wk = new WhiteKey(wKeys[i], wPos[i]-35,0); //create a new white Key with [i] Pitch, at that x position and at y =0 position
wk.MouseDown += onRightClick; //holds the Duration on Right Click
wk.MouseUp += onMouseUp;
wk.Click += new EventHandler(KeyClick); //Go to KeyClick Method whenever a key is pressed
this.panel1.Controls.Add(wk); //Give it control (to play and edit)
}
Methods controlling the time
private void onRightClick(object sender, MouseEventArgs e)
{
wk = sender as WhiteKey;
duration = 0;
t1.Enabled = true;
t1.Tick += timeTick;
t1.Interval = 100;
}
private void timeTick(object sender, EventArgs e)
{
duration++;
}
private void onMouseUp (object sender, MouseEventArgs e)
{
t1.Enabled = false;
String time = "Key: " + pitch + "\nDuration: " +duration ; //Test purposes to see if timer works
MessageBox.Show(time);
}
You are trying to measure time, don't use Timer, use Stopwatch.
You can find C# Stopwatch Exmples at dotnetpearls.com.
In abstract this is what you would want to do is something like this:
private void onRightClick(object sender, MouseEventArgs e)
{
stopwatch.Reset();
stopwatch.Start();
}
private void onMouseUp (object sender, MouseEventArgs e)
{
stopwatch.Stop();
String msg = "Duration in seconds: " + (stopwatch.ElapsedMilliseconds / 1000.0).ToString("0.00");
MessageBox.Show(msg);
}
Note: you may want to change the units or the string format.
Notes on using timer:
1) System.Windows.Forms.Timer uses the message loop of your window, this means that it may get delayed because the window is busy handling other events (such as click). For a better behaviour use System.Threading.Timer.
2) If using System.Windows.Forms.Timer don't set the Tick event handler each click. The event handler will execute once for each time you add it.
That is:
private void onRightClick(object sender, MouseEventArgs e)
{
wk = sender as WhiteKey;
duration = 0;
t1.Enabled = true;
//t1.Tick += timeTick; you should add this only once not each click
t1.Interval = 100;
}
3) If you use System.Threading.Timer you may want to make the variable duration volatile.
t1.Tick += timeTick;
By the way in your code sample you subscribe to the 'Tick' timer event each time on Right mouse click.
So if you click 2 times the
private void timeTick(object sender, EventArgs e)
method will be called twice, and 'duration++' will be executed twice. Your event subscription code should be executed only once for the timer.
P.S. If you need to measure duration, Timer is not the best way to do it.

Categories