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.
Related
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''");
}
I have one button name called Submit. I would like to trigger Auto Button_Click event for every 5sec.
E.g:
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Welcome to WPF....");
}
Every 5sec I need to call this Button_Click event to show Message like "Welcome to Google...." automatically.
Please help me to solve.
In Wpf, you could use DispatcherTimer
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//Timer
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += (s, ev) => btnClickMe.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
timer.Interval = new TimeSpan(0, 5, 0);
timer.Start();
}
create a timer to run every 5 seconds and send: Button_Click(null, null);
public static void Main()
{
var timer = new Timer();
timer.Elapsed+= OnTimedEvent;
timer.Interval=5000;
timer.Enabled=true;
Console.ReadKey();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Button_Click(null, null);
}
It is as simple as this. Create a timer of 5 seconds duration and do this on the timer_tick event.
buttonName.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent));
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...
What would happen with the code below if Execute() takes, say, 3000ms to finish, but is being called every 1000ms due to the timer interval?
Timer _timer = new Timer();
private void setupTimer()
{
_timer.Tick += new EventHandler(pollingTimeElapsed);
_timer.Interval = 1000;
_timer.Enabled = true;
_timer.Start();
}
private void pollingTimeElapsed(object sender, EventArgs e)
{
Execute();
}
EDIT: I am using System.Windows.Forms.Timer, since System.Timers.Timer doesn't have .Tick
I'm assuming you are using the System.Timers.Timer class.
Since AutoReset has the default value (which is True), the Elapsed event will be fired for each time 1000ms has elapsed.
If you want to fire the event only one time, set AutoReset to False.
If you do not want to fire the event while your execute-code is running, do the following:
Timer _timer = new Timer();
private void setupTimer() {
_timer.Tick += new EventHandler(pollingTimeElapsed);
_timer.Interval = 1000;
_timer.Enabled = true;
_timer.Start();
}
private void pollingTimeElapsed(object sender, EventArgs e) {
try {
_timer.Stop()
Execute();
} finally {
_timer.Start()
}
}
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();
}
}