dispatchertimer not continue when messagebox is shown - c#

In my wp8 app, i have a countdown timer using dispatchertimer. I click a button and show a messagebox The countdown timer doesn't continue, when the messagebox is shown. I want the timer_counter continue to countdown during the time messagebox is shown.
I have tried System.Timers.Timer, but it cannot find the class. Also, I tried the DispatcherPriority to make the timer work at background. But it cannot find the class, too.
private DispatcherTimer timer;
private int timer_counter;
public MainPage()
{
InitializeComponent();
// set timer
timer_counter = 30; // 30 secounds
CountdownTimer.Text = new TimeSpan(0, 0, timer_counter).ToString("mm':'ss"); // show the time to textbox
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1); // interval: 1 second
timer.Tick += new EventHandler(dispatcherTimer_Tick);
timer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
timer_counter--; // countdown
CountdownTimer.Text = new TimeSpan(0, 0, timer_counter).ToString("mm':'ss"); // show the time to textbox
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult result = MessageBox.Show(
"clickbutton",
"alert",
MessageBoxButton.OK);
}

This is the design of DispatcherTimer. In your example the timer tick callbacks are run in the UI thread. And when the UI thread is in use - it waits...

Related

dispatcherTimer not restarting

I'm implementing a countdown in my app
private async void Window_Activated(object sender, WindowActivatedEventArgs args)
{
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0,1,0);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
TimeSpan timeSpan = new TimeSpan(blockTime.Hours, blockTime.Minutes, blockTime.Seconds);
if (timeSpan != TimeSpan.Zero)
{
timeSpan = timeSpan.Subtract(TimeSpan.FromMinutes(1));
Countdown_TexBlock.Text = String.Format("{0}:{1}", timeSpan.Hours, timeSpan.Minutes);
dispatcherTimer.Start();
}
else
{
dispatcherTimer.Stop();
}
}
The code works but only one time
For example I put 15 minutes in the blocktime (the time that the countdown will be running)
after a minute the countdown.text would be 0:14.
So only works after the first minute
Is not supposed to be restarted with dispatcher.start()
In the code that you posted, I don't see the blockTime variable being changed to any other value than it has in the beginning. This means that on every tick of dispatchTimer the value of the timeSpan.Subtract expression will always evaluate to the same 14 minutes. In your code, that 14 minutes is assigned to a local vaiable that is disposed when the tick is over. This gives the appearance that the dispatchTimer has stopped issuing Tick when it hasn't.
Here's what I ran that works as expected (for testing, I changed the minutes to seconds to make it observable in a reasonable time).
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
// Create the dispatch timer ONCE
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += DispatcherTimer_Tick;
dispatcherTimer.Interval = TimeSpan.FromSeconds(1);
// This will restart the timer every
// time the window is activated
this.Activated += (sender, e) =>
{
startOrRestartDispatchTimer();
};
}
private void startOrRestartDispatchTimer()
{
dispatcherTimer.Stop(); // If already running
blockTime = TimeSpan.FromSeconds(15);
Countdown_TexBlock.Text = blockTime.ToString();
dispatcherTimer.Start();
}
private void DispatcherTimer_Tick(object sender, object e)
{
if (blockTime > TimeSpan.Zero)
{
blockTime = blockTime.Subtract(TimeSpan.FromSeconds(1));
Countdown_TexBlock.Text = blockTime.ToString();
if (blockTime == TimeSpan.Zero)
{
Countdown_TexBlock.Text = "Done";
dispatcherTimer.Stop();
}
}
}
TimeSpan blockTime = TimeSpan.FromSeconds(15);
private DispatcherTimer dispatcherTimer;
// This will restart the timer when the button is clicked.
private void buttonRestart_Click(object sender, RoutedEventArgs e) =>
startOrRestartDispatchTimer();
}

C# - Win Form stopping Timer tick

This is my implementation of a Win Form app that has a countdown timer:
readonly DateTime myThreshold;
public Form1()
{
InitializeComponent();
myThreshold = Utils.GetDate();
Timer timer = new Timer();
timer.Interval = 1000; //1 second
timer.Tick += new EventHandler(t_Tick);
timer.Start();
//Threshold check - this only fires once insted of each second
if (DateTime.Now.CompareTo(myThreshold) > 0)
{
// STOP THE TIMER
timer.Stop();
}
else
{
//do other stuff
}
}
void t_Tick(object sender, EventArgs e)
{
TimeSpan timeSpan = myThreshold.Subtract(DateTime.Now);
this.labelTimer.Text = timeSpan.ToString("d' Countdown - 'hh':'mm':'ss''");
}
The wanted behavior is to stop the timer and the tick function when the threshold is reached.
This now does not happens because the check is only executed once since it is placed in the Form1 initialization.
Does exist a way to add this check in a way to immediately stop the Timer once a condition has been meet?
If we define timer as a class field (so it can be accessed from all methods in the class), then we can just add the check to the Tick event itself, and stop the timer from there:
private Timer timer = new Timer();
void t_Tick(object sender, EventArgs e)
{
// Stop the timer if we've reached the threshold
if (DateTime.Now > myThreshold) timer.Stop();
TimeSpan timeSpan = myThreshold.Subtract(DateTime.Now);
this.labelTimer.Text = timeSpan.ToString("d' Countdown - 'hh':'mm':'ss''");
}

WPF DispatcherTimer not stop working once I started it more than once

I want to make a timer to update the UI counter using DispatcherTimer class.
Here's my code:
private static DispatcherTimer timer;
private static int count;
//counter is TextBlock in WPF xaml
private void countdownBtn_Click(object sender, RoutedEventArgs e)
{
count = 3;
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
timer.Tick += CountDown;
timer.Start();
}
private void CountDown(object sender, EventArgs e)
{
//if counter becomes 0, stop the counter
if (count <= 0)
{
counter.Visibility = Visibility.Hidden;
timer.Stop();
return;
}
if (counter.Visibility == Visibility.Hidden)
{
counter.Text = count.ToString();
counter.Visibility = Visibility.Visible;
}
else
{
count--;
counter.Visibility = Visibility.Hidden;
}
}
This code works fine if I click the button one time and wait it to complete its task for 3 seconds. But if I clicked the button 2 times in a row, it will continue following this:
If I click the button, the counter will be updated with more than 1 threads (make it visible and hidden faster than usual).
It will continue working even after timer.Stop() is executed ( it will enter loop CountDown -> if(count<=0) -> timer.Stop() -> return; -> CountDown -> if(count<=0) -> ... ).
And if I want to do something after the timer is stopped, where should I modify my code?
Every time you click the button a new DispatcherTimer is created with the previous ones still running.
You should stop and then dispose the old timer before create new ones.

WPF event that triggers after the mouse stops moving

I am writing a WPF application.
I want to trigger an event once the mouse stops moving.
This is how I tried to do it. I created a timer which counts down to 5 seconds. This timer is "reset" every time the mouse moves.
This idea is that the moment the mouse stops moving, the timer stops being reset, and counts down from 5 to zero, and then calls the tick event handler, which displays a message box.
Well, it doesn't work as expected, and it floods me with alert messages. What am I doing wrong?
DispatcherTimer timer;
private void Window_MouseMove(object sender, MouseEventArgs e)
{
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 5);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("Mouse stopped moving");
}
It is not necessary to create a new timer on every MouseMove event. Just stop and restart it. And also make sure that it is stopped in the Tick handler, since it should be fired only once.
private DispatcherTimer timer;
public MainWindow()
{
InitializeComponent();
timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
MessageBox.Show("Mouse stopped moving");
}
private void Window_MouseMove(object sender, MouseEventArgs e)
{
timer.Stop();
timer.Start();
}
You need to unhook the event before hooking it again like this -
private void poc_MouseMove(object sender, MouseEventArgs e)
{
if (timer != null)
{
timer.Tick-= timer_Tick;
}
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 5);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
Explanation
What you doing is whenever a mouse moves, you create a new instance of DispatcherTimer and hook Tick event to it without unhooking the event for previous instance. Hence, you see flooded messages once timer stops for all the instances.
Also, you should unhook it otherwise previous instance won't be garbage collected since they are still strongly referenced.

BackGround Thread with timer for application level-WPF Application

I have a wpf application(No MVVM), this application requires several background thread(Runs with specific time interval).
These thread should be on Application Level i.e. if user is on any WPF Window, these threads should be active.
Basically these thread will are using external resources so locking is also required.
Kindly tell me the best way to do this.
If you want to execute an action periodically in a WPF application you can use the DispatcherTimer class.
Put your code as the handler of the Tick event and set the Interval property to whatever you need. Something like:
DispatcherTimer dt = new DispatcherTimer();
dt.Tick += new EventHandler(timer_Tick);
dt.Interval = new TimeSpan(1, 0, 0); // execute every hour
dt.Start();
// Tick handler
private void timer_Tick(object sender, EventArgs e)
{
// code to execute periodically
}
private void InitializeDatabaseConnectionCheckTimer()
{
DispatcherTimer _timerNet = new DispatcherTimer();
_timerNet.Tick += new EventHandler(DatabaseConectionCheckTimer_Tick);
_timerNet.Interval = new TimeSpan(_batchScheduleInterval);
_timerNet.Start();
}
private void InitializeApplicationSyncTimer()
{
DispatcherTimer _timer = new DispatcherTimer();
_timer.Tick += new EventHandler(AppSyncTimer_Tick);
_timer.Interval = new TimeSpan(_batchScheduleInterval);
_timer.Start();
}
private void IntializeImageSyncTimer()
{
DispatcherTimer _imageTimer = new DispatcherTimer();
_imageTimer.Tick += delegate
{
lock (this)
{
ImagesSync.SyncImages();
}
};
_imageTimer.Interval = new TimeSpan(_batchScheduleInterval);
_imageTimer.Start();
}
These three threads a intialized on App_OnStart
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
try
{
_batchScheduleInterval = Convert.ToInt32(ApplicationConfigurationManager.Properties["BatchScheduleInterval"]);
}
catch(InvalidCastException err)
{
TextLogger.Log(err.Message);
}
Helper.SaveKioskApplicationStatusLog(Constant.APP_START);
if (SessionManager.Instance.DriverId == null && _batchScheduleInterval!=0)
{
InitializeApplicationSyncTimer();
InitializeDatabaseConnectionCheckTimer();
IntializeImageSyncTimer();
}
}

Categories