How to calculate that how many times tick event occur? - c#

What I really want to do, I want to calculate that how many times tick event occur. Actually I want to make check on it that if this event occurs 5 time.
Then messagebox should displayed.
Here is my code :
public partial class MainWindow : Window
{
int i = 0;
int points = 0;
int counter = 0;
public MainWindow()
{
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(this.playMyAudioFile);
TimeSpan ts = dispatcherTimer.Interval = new TimeSpan(0, 0, 2);
dispatcherTimer.Start();
if (counter == 5)
{
dispatcherTimer.Stop();
}
InitializeComponent();
}
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
// some code
label1.Content = points;
}
}
private void playMyAudioFile(object sender, EventArgs e)
{
Random rd = new Random();
i = rd.Next(1, 26);
mediaElement1.Source = new Uri(#"D:\Project C#\A-Z\" + i + ".mp3");
mediaElement1.Play();
}
}

Using await, instead of a timer, makes this particular task much easier:
public static async Task makeMusic(TimeSpan timespan)
{
for (int i = 0; i < 5; i++)
{
//this assumes you can remove the parameters from this method
playMyAudioFile();
await Task.Delay(timespan);
}
MessageBox.Show("All done!");
}
You can make the count a parameter, if it needs to be configurable, or remove the timespan as a parameter if it need never change.

Servy's solution is a lot cleaner than using a timer. But if you insist on using a timer, I would suggest this:
private int counter = 0;
private Random rd = new Random();
private void playMyAudioFile(object sender, EventArgs e)
{
i = rd.Next(1, 26);
mediaElement1.Source = new Uri(#"D:\Project C#\A-Z\" + i + ".mp3");
mediaElement1.Play();
++counter;
if (counter == 5)
{
dispatcherTimer.Stop();
}
}
I think that the sender is the dispatcher timer, so you can probably write:
var timer = (DispatcherTimer)sender;
timer.Stop();
And, please, replace this:
TimeSpan ts = dispatcherTimer.Interval = new TimeSpan(0, 0, 2);
With:
TimeSpan ts = dispatcherTimer.Interval = TimeSpan.FromSeconds(2);
When I see new TimeSpan(0, 0, 2), I have to think about what that signifies. Is it minutes, seconds, and milliseconds? Days, hours, and minutes? Hours, minutes, and seconds?
TimeSpan.FromSeconds(2), though, is explicit. There is absolutely no ambiguity.

Related

My Timer is not reset when click on reset button C#

initialize the components
System.Timers.Timer t;
int h, m, s;
I want to reset the timer when I click on the reset button and turn it to 00.00.00, but when I try to reset it with the code the timer stops. But when I start the timer and stop it, it doesn't get reset to 00.00.00
Method of timer
private void OnTimeEvent(object sender, ElapsedEventArgs e)
{
Invoke(new Action(() =>
{
s += 1;
if (s == 60)
{
s = 0;
m += 1;
}
if (m == 60)
{
m = 0;
h += 1;
}
lbltime.Text = string.Format("{0}:{1}:{2}", h.ToString().PadLeft(2, '0'),
m.ToString().PadLeft(2, '0'), s.ToString().PadLeft(2, '0'));
}));
}
Form load event
t = new System.Timers.Timer();
t.Interval = 1000;
t.Elapsed += OnTimeEvent;
t.Start();
Reset Button Which is not working
t.Dispose();
Try something like this:
Stopwatch stopwatch = Stopwatch.StartNew();
private void OnTimeEvent(object sender, ElapsedEventArgs e)
{
Invoke(new Action(() => lbltime.Text = stopwatch.Elapsed.ToString("hh:mm:ss")));
}
private void OnResetButtonClick(object sender, EventArgs e)
{
stopwatch.Restart();
}
This uses a stopwatch to measure the time, and a timer to update the label from the stopwatch. This will also be much more accurate since timers do not guarantee any particular tick-frequency.

WPF / C# (No MVVM) Timer with Countdown Clock

Good day all,
I'm struggling with a coding problem and I need some help. My process requires a 300 second (5 min) timer that fires an event to refresh a Grid Control. That works just fine. The problem is, I need to countdown the 5 mins/300 seconds to the user so they know the next fresh happens in "X" seconds. The goal is to countdown, refresh, and show the user the next refresh.
All code samples below are examples of things I tried.
I have code that works for the refresh, but something strange happens after the first execution. The timer counts down to 0, refreshes, and then restarts at 300 seconds again (good), but each tick down flashes a second timer behind it. So I see 300, 299, 298, ... and then another 300, 299, 298, ...; therefore, it looks like 300, 299, 298, 300, 297, 299, 296, 298, etc. It's nauseating to watch. Let alone trying to watch 20 minutes in...
My 300-second timer is a System.Timers.Timer int eh below example (Reminder, this works):
public partial class MasterControl
{
private Timer _t;
public MasterControl()
{
InitializeComponent();
}
public void Dispose()
{
_t?.Dispose();
_handle?.Dispose();
}
private void Master_OnLoaded(object sender, RoutedEventArgs e)
{
var fd = new FillMaster();
GridMaster.ItemsSource = fd.GridPopulate("TblName", App.UserName);
_t = new Timer();
_t.Elapsed += OnTimedEvent;
_t.Interval = 300000;
_t.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Dispatcher.Invoke(() =>
{
try
{
var fd = new FillMaster();
GridMaster.ItemsSource = fd.GridPopulate("TblName", App.UserName);
}
catch (SqlException)
{
/* swallow */
}
});
}
}
What I tried to do was add a countdown that fills a label.
I added
private TimeSpan _time;
private DispatcherTimer _timer;
And I adjusted the OnTimedEvent code to the below example and it didn't work. This is where it started to double up on refresh. I tried GC to see if that would work. No dice.
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Dispatcher.Invoke(() =>
{
try
{
var fd = new FillMaster();
GridMaster.ItemsSource = fd.GridPopulate("IntakeCheckList", App.UserName);
TbCountDown.Content = "";
_time = TimeSpan.FromSeconds(60);
_timer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
TbCountDown.Content = _time.ToString("c");
if (_time == TimeSpan.Zero)
{
_timer.Stop();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
_time = _time.Add(TimeSpan.FromSeconds(-1));
}, Application.Current.Dispatcher);
_timer.Start();
}
catch (SqlException)
{
/* swallow */
}
});
}
I also found some code that casued the same problem.
private void Countdown(int count, TimeSpan interval, Action<int> ts)
{
var dt = new DispatcherTimer {Interval = interval};
dt.Tick += (_, a) =>
{
if (count-- == 0)
dt.Stop();
else
ts(count);
};
ts(count);
dt.Start();
}
Then I added the following to the to OnTimedEvent
Countdown(30, TimeSpan.FromSeconds(5), cur => TbCountDown.Content = cur.ToString());
As seen here
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Dispatcher.Invoke(() =>
{
Countdown(30, TimeSpan.FromSeconds(5), cur => TbCountDown.Content = cur.ToString());
try
{
var fd = new FillMaster();
GridMaster.ItemsSource = fd.GridPopulate("IntakeCheckList", App.UserName);
}
catch (SqlException)
{
/* swallow */
}
});
}
This also failed with the exact same problem.
Ultimately, is there a way to get the countdown from the System.Timers.Timer or something else you can help me with?
Thank you!
You don't actually need more than a simple DispatcherTimer and a DateTime that is cyclically reset to the current time + 300 seconds.
public partial class MainWindow : Window
{
private readonly DispatcherTimer timer = new DispatcherTimer();
private DateTime endTime;
public MainWindow()
{
InitializeComponent();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += new EventHandler(OnTimerTick);
timer.Start();
}
private void OnTimerTick(object sender, EventArgs e)
{
var now = DateTime.Now;
if (endTime < now)
{
endTime = now.AddSeconds(300);
}
label.Content = (endTime - now).ToString(#"mm\:ss");
}
}

Making an alarm with C# to ring on specific constant times, throughout a day

I'm trying to make an alarm to ring on specific times ( for example; every five minutes after 9:30 am till 4 pm). So, I want to write a code that rings in 9:30 and 9:35 and ... . but with every approach ultimately I get an error. in my code I have a string that includes the times, but I cannot use that string or group in a if(...) to make the alarm. it's fine with just one number with var..., where am I wrong?
{
public partial class Form1 : Form
{
System.Timers.Timer timer;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime currentTime = DateTime.Now;
string[] DailyTime = { 093000, 093500 };
if (((currentTime.Hour * 10000) + (currentTime.Minute *100) + currentTime.Second) == DailyTime)
{
timer.Stop();
try
{
SoundPlayer player = new SoundPlayer();
player.SoundLocation = #"C:\Windows\Media\Time interval alarm\FiveH.wav";
player.Play();
private void Form1_Load(object sender, EventArgs e)
{
timer = new System.Timers.Timer();
timer.Interval = 1000 * 60 * 5; //5 minutes
timer.Elapsed += Timer_Elapsed;
InitializeTimer(); //this method makes sure the timer starts at the correct time
}
The timer initialization method:
private async void InitializeTimer()
{
while (!timer.Enabled) //keep looping until timer is initialized
{
//if the minute is a multiple of 5 (:00, :05, ...) start the timer
if (DateTime.Now.Minute % 5 == 0 && DateTime.Now.Second == 0)
{
timer.Start();
TriggerAlarm(); //trigger the alarm initially instead of having to wait 5min
}
else
{
await Task.Delay(100);
}
}
}
You could store the times and alarm paths in a dictionary:
Dictionary<TimeSpan, string> dict = new Dictionary<TimeSpan, string>()
{
{ new TimeSpan(9, 30, 0), #"C:\Windows\Media\Time interval alarm\FiveH.wav" },
{ new TimeSpan(9, 35, 0), #"C:\Windows\Media\Time interval alarm\Whatever.wav" },
{ new TimeSpan(9, 40, 0), #"C:\Windows\Media\Time interval alarm\Whatever1.wav" },
{ new TimeSpan(9, 45, 0), #"C:\Windows\Media\Time interval alarm\Whatever2.wav" },
//...
{ new TimeSpan(16, 0, 0), #"C:\Windows\Media\Time interval alarm\Whatever3.wav" }
};
The Timer_Elapsed event, which will trigger every 5 min since the alarm is started
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
TriggerAlarm();
}
The method that plays the sound
private static void TriggerAlarm()
{
TimeSpan alarmTime = new TimeSpan(DateTime.Now.Hour, DateTime.Now.Minute, 0);
if (dict.TryGetValue(alarmTime, out string alarmFile))
{
using (SoundPlayer player = new SoundPlayer(alarmFile))
{
player.Play();
}
}
else
{
//this alarm time is not found in the dictionary,
//therefore, no alarm should be played at this time (e.g. 16:05:00)
}
}

I need my random values to look like they are rolling C#

I have five dice labels and I have a method Roll() that sets their
text value. At the moment when the roll method happens it just makes the numbers appear, but I would like them to look like they are rolling.
Here is what I have
//Roll() simulates the rolling of this die.
public void Roll()
{
if (Active) {
faceValue = random.Next(1, 7);
label.Text = faceValue.ToString();
}
}
Roll() is called from another class like this:
for (int i = 0; i < dice.Length; i++){
dice[i].Roll();
}
My Question is:
How can I let it looks like they are rolling through a set of numbers then stop on a number ?
Try this
public async void Roll()
{
if (Active)
{
for (int i=0;i<20;i++) //Number of rolls before showing final
{
await Task.Delay(100);
label.Text = random.Next(1, 7).ToString();
}
}
}
I tested a Little and this Looks good done in WPF with a DispatcherTimer:
DispatcherTimer timer = new DispatcherTimer();
private void Button_Click(object sender, RoutedEventArgs e)
{
timer.Tick += Roll;
timer.Interval = new TimeSpan(1);
Random r = new Random();
timer.Start();
}
Random r = new Random();
public void Roll(object sender, EventArgs e)
{
increment++;
if (increment >= 250)
{
timer.Stop();
increment = 0;
}
DiceLabel.Content = r.Next(1, 7).ToString();
timer.Interval = new TimeSpan(increment*3000);
}
If you want it faster or longer you can play with the value from:
timer.Interval = new TimeSpan(increment*3000);
here to set the time between the new number is shown.
And for the time to Dice is rolling, you can play with:
if (increment >= 250)
Hope that helps, have fun.

c# how to run multiple timer in loop. one timer after another

I want to run timer countdown (DispatchTimer) multiple times in a loop, one after another. I want to wait until one timer stops and then run another one.
I'm gonna try something like this:
public TimeSpan CurrentTimeSpan;
private void RunInterval()
{
for (int i = 0; i < 10; i++)
{
RunTimer(new TimeSpan(0, 0, 0, 30));
}
}
private void RunTimer(TimeSpan Timer)
{
DispatcherTimer timer1 = new DispatcherTimer();
timer1.Interval = new TimeSpan(0, 0, 0, 1);
CurrentTimeSpan = Timer;
timer1.Tick += Timer1OnTick;
}
private void Timer1OnTick(object sender, object o)
{
DispatcherTimer timer = (DispatcherTimer) sender;
CurrentTimeSpan = CurrentTimeSpan.Subtract(timer.Interval);
if (CurrentTimeSpan.TotalSeconds == 0)
{
timer.Stop();
}
}
My problem is that method RunInterval or RunTimer doesn't wait until timer will stop.
What can I do about it?
Maybe something like this?
private int hitCount = 0;
public TimeSpan CurrentTimeSpan;
private void RunInterval()
{
RunTimer(new TimeSpan(0, 0, 0, 30));
}
private void RunTimer(TimeSpan Timer)
{
DispatcherTimer timer1 = new DispatcherTimer();
timer1.Interval = new TimeSpan(0, 0, 0, 1);
CurrentTimeSpan = Timer;
timer1.Tick += Timer1OnTick;
}
private void Timer1OnTick(object sender, object o)
{
DispatcherTimer timer = (DispatcherTimer)sender;
if(hitCount == 10)
{
timer.Tick -= Timer1OnTick
}
CurrentTimeSpan = CurrentTimeSpan.Subtract(timer.Interval);
if (CurrentTimeSpan.TotalSeconds == 0)
{
timer.Stop();
}
}
Instead of looping to create the timers just keep track in the event how many times it's been hit and then unhook the event once that target has been achieved.

Categories