Timer to continue when message box is shown - c#

I am looking to allow a timer to continue counting down even when a message box is shown. The message box is shown when the timer hits 30 seconds and zero seconds. However, currently the timer stops until the message box is closed by the user. My current code is below;
_Time = TimeSpan.FromSeconds(60);
_Timer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
O2_Timer.Text = _Time.ToString("c");
if (_Time == TimeSpan.FromSeconds(30))
{
MessageBox.Show("timer is at 30 seconds");
}
if (_Time == TimeSpan.Zero)
{
_Timer.Stop();
MessageBox.Show("timer done");
Sub_Depth.Text = null;
}
_Time = _Time.Add(TimeSpan.FromSeconds(-1));
}, Application.Current.Dispatcher);
_Timer.Start();
Thank you in advance.

I think the most effective thing would be to create a new thread and call it,
The Messagebox is blocking because its on the same thread if you will create and start a new thread it will work
_Time = TimeSpan.FromSeconds(60);
//Creating a new thread
Thread newMessage = new Thread(runThread);
_Timer = new DispatcherTimer(new TimeSpan(0, 0, 1),DispatcherPriority.Normal, delegate
{
O2_Timer.Text = _Time.ToString("c");
if (_Time == TimeSpan.FromSeconds(30))
{
//Starting the thread
newMessage.Start();
}
if (_Time == TimeSpan.Zero)
{
_Timer.Stop();
MessageBox.Show("timer done");
Sub_Depth.Text = null;
}
_Time = _Time.Add(TimeSpan.FromSeconds(-1));
}, Application.Current.Dispatcher);
_Timer.Start();
private static void runThread(){
//The thread function
MessageBox.Show("timer is at 30 seconds");
}

Related

label disappears if the countdown timer gets zero

i have a Textblock (tbTime) which shows the countdown timer. when it gets zero, the Textblock (tbTime) shows still the zero values. But i wanna make this Textblock (tbTime) disappear, after the countdown timer reaches to zero.
Could anyone help me, please?
C# Code
public partial class InfoScreen : Window
{
DispatcherTimer timer;
TimeSpan time;
public InfoScreen()
{
InitializeComponent();
AppearingNext();
time = TimeSpan.FromSeconds(10);
timer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
tbTime.Text = time.ToString("ss");
if (time == TimeSpan.Zero) timer.Stop();
time = time.Add(TimeSpan.FromSeconds(-1));
}, Application.Current.Dispatcher);
if (tbTime.Text == "00") //My code doesn't work!
{
tbTime.Visibility = Visibility.Hidden;
}
}
private async void AppearingNext()
{
await Task.Delay(TimeSpan.FromSeconds(10));
VisbilityPanel.Visibility = Visibility.Visible;
}
private void AgreementClick(object sender, RoutedEventArgs e)
{
var registration = new Reset_Register();
registration.Show();
Close();
}
}
One solution is put your code that hide the textblock inside the callback of the timer:
timer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate {
tbTime.Text = time.ToString("ss");
if (tbTime.Text == "00") {
tbTime.Visibility = Visibility.Hidden;
}
if (time == TimeSpan.Zero) timer.Stop();
time = time.Add(TimeSpan.FromSeconds(-1));
}, Application.Current.Dispatcher);

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)
}
}

How to delay a timer from running or start it based on current date time

I have console application am using as demo to an App, it prints "hello", based on the timespan its expected to alert the user. when its not yet the timespan, i want to delay the app from printing hello and resume when its time.
public static async void timeCounter(int delae)
{
//This is suppose to cause a delay but it instead initiate the
//TimerOperation_Tick method.
await Task.Delay(delae);
// timer countdown
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000; // 1 second
timer.Elapsed += new ElapsedEventHandler(TimerOperation_Tick);
timer.Start();
if (obj.SubmissionCheck == true)
{
timer.Stop();
}
}
/// the event subscriber
private static void TimerOperation_Tick(object e, ElapsedEventArgs args)
{
if (timeFrame != 0)
{
Console.WriteLine("hi" + timeFrame);
timeFrame --;
if (timeFrame < 1)
{
obj.SubmissionCheck = true;
nt.Remove(obj);
startNotification();
}
}
}
Try setting timer.Enabled = false; This will prevent the timer ticks from occurring.

System.Timers.Timer fires second time a few milliseconds later

In my application I have a System.Timers.Timer which fires a second time a few milliseconds later.
Declaration of the timer:
mRecipeTimer = new System.Timers.Timer(30000);
mRecipeTimer.Start();
mRecipeTimer.Elapsed += new ElapsedEventHandler(mRecipeTimer_Elapsed);
Timer elapse event:
void mRecipeTimer_Elapsed(object sender, ElapsedEventArgs e)
{
int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
if (sync == 0)
{
Thread.CurrentThread.Name = string.Format("timer, started at {0} ({1})", DateTime.Now, DateTime.Now.Millisecond);
Log.Info("Recipe timer elapsed.");
// some code
syncPoint = 0;
}
}
And this is what I see in my logs:
2012-01-31 11:17:26,797 [timer, started at 1/31/2012 11:17:26 AM (797)] INFO - Recipe timer elapsed.
2012-01-31 11:17:27,875 [timer, started at 1/31/2012 11:17:27 AM (875)] INFO - Recipe timer elapsed.
2012-01-31 11:17:56,797 [timer, started at 1/31/2012 11:17:56 AM (797)] INFO - Recipe timer elapsed.
2012-01-31 11:17:57,875 [timer, started at 1/31/2012 11:17:57 AM (875)] INFO - Recipe timer elapsed.
I allready placed an interlock so that only one action may run at the same time. But unfornately the timer fires its event twice and I don't know why.
You can always disable/enable the timer while the event is being processed, i.e.,
void mRecipeTimer_Elapsed(object sender, ElapsedEventArgs e)
{
mRecipeTimer.Enabled = false; //<---- disable
int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
if (sync == 0)
{
Thread.CurrentThread.Name = string.Format("timer, started at {0} ({1})", DateTime.Now, DateTime.Now.Millisecond);
Log.Info("Recipe timer elapsed.");
// some code
syncPoint = 0;
}
mRecipeTimer.Enabled = true; //<---- enable
}

Categories