I have the following timer implementation. But the timer is not running every 5 seconds as needed. How can make this run every 5 seconds. At present its running about once in 30 seconds.
private void button1_Click(object sender, RoutedEventArgs e)
{
msgsent = 0;
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 5);
bool isenable = timer.IsEnabled;
timer.Start();
}
private async void timer_Tick(object sender, object e)
{
if (geo == null)
{
geo = new Geolocator();
}
Geoposition posi = await geo.GetGeopositionAsync();
if (posi.Coordinate.Point.Position.Latitude <= 12.9227 && posi.Coordinate.Point.Position.Longitude >= 080.1320)
{
if (msgsent <=1)
{
msgsent = msgsent + 1;
ShowDialog(new MessageDialog("Your Bus has crossed xyz"));
}
}
}
I'll give you a hint. If you understand where each goes, then it should be clear. If not, you will once you get better.
// in the class definition
int msgsent;
Timer timer;
and
// in the constructor
timer = new Timer();
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 5);
and
// in the Button.Click event handler
timer.Start();
and
// in the Timer.Tick event handler
timer.Stop();
/* do your work here */
timer.Start();
There will be further issues when the user is clicking the button while you're doing your work, but that's beyond the scope of this question.
Related
I have a timer that repeats at 1 second intervals. Users can Start() or Stop() the timer.
System.Windows.Form.Timer timer = new();
timer.Interval = 1000;
timer.Tick += (sender, e) =>
{
// Perform the action...
}
The problem is that in case of timer.Stop() it reacts immediately after pressing, but in case of timer.Start() it works after 1 second. This may feel strange to users.
So I solved it like this:
System.Windows.Form.Timer timer = new();
timer.Interval = 1;
timer.Tick += (sender, e) =>
{
if (timer.Interval == 1)
{
timer.Interval = 1000;
}
// Perform the action...
}
private void StopButton_Click(object sender, EventArgs e)
{
timer.Stop();
timer.Interval = 1;
}
However, there is a problem that the timer's Interval must be continuously set to 1. One timer is fine, but having multiple complicates things.
Is there any other way?
Following comments from #jmcilhinney and #Zohar Peled, I solved it like this:
System.Windows.Form.Timer timer = new();
timer.Interval = 1000;
timer.Tick += (sender, e) =>
{
StartOnFirstTimer();
}
private void StartOnFirstTimer()
{
// Perform the action...
}
private void StartButton_Click(object sender, EventArgs e)
{
StartOnFirstTimer();
timer.Start();
}
It is extracted the part corresponding to the timer's Tick event into a method and call it before starting it.
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();
}
I need to do some stuff in my application while application is running. I put it in dispatcher to work withing given time intervals. But now I want to randomized things.
I want to set random time intervals.
dTSettings.Tick += new EventHandler(dTSettings_Tick);
dTSettings.Interval = new TimeSpan(0, SetRandomTimer(), 0);
dTSettings.Start();
how to do that?
private DispatcherTimer _timer = new DispatcherTimer();
private Random rand = new Random();
public void InitAndStartTimer()
{
_timer.Tick += dispatcherTimer_Tick;
_timer.Interval = TimeSpan.FromSeconds(rand.Next(1, 10)); // From 1 s to 10 s
_timer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
_timer.Interval = TimeSpan.FromSeconds(rand.Next(1, 10)); // From 1 s to 10 s
// Do your work.
}
I have a Windows.Forms.Timer in my code, that I am executing 3 times. However, the timer isn't calling the tick function at all.
private int count = 3;
private timer;
void Loopy(int times)
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
count--;
if (count == 0) timer.Stop();
else
{
// Do something here
}
}
Loopy() is being called from other places in the code.
Try using System.Timers instead of Windows.Forms.Timer
void Loopy(int times)
{
count = times;
timer = new Timer(1000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
throw new NotImplementedException();
}
If the method Loopy() is called in a thread that is not the main UI thread, then the timer won't tick.
If you want to call this method from anywhere in the code then you need to check the InvokeRequired property. So your code should look like (assuming that the code is in a form):
private void Loopy(int times)
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
Loopy(times);
});
}
else
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
}
I am not sure what you are doing wrong it looks correct, This code works: See how it compares to yours.
public partial class Form1 : Form
{
private int count = 3;
private Timer timer;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Loopy(count);
}
void Loopy(int times)
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
count--;
if (count == 0) timer.Stop();
else
{
//
}
}
}
Here's an Rx ticker that works:
Observable.Interval(TimeSpan.FromSeconds(1))
.Take(3)
.Subscribe(x=>Console.WriteLine("tick"));
Of course, you can subscribe something more useful in your program.
you may have started the timer from another thread, so try invoking it from the correct thread.
for example, instead of:
timerX.start();
Use:
Invoke((MethodInvoker)delegate { timerX.Start(); });
Check if your timer in properties is enabled.
Mine was false and after setting to true it worked.
If you are using Windows.Forms.Timer then should use something like following.
//Declare Timer
private Timer _timer= new Timer();
void Loopy(int _time)
{
_timer.Interval = _time;
_timer.Enabled = true;
_timer.Tick += new EventHandler(timer_Elapsed);
_timer.Start();
}
void timer_Elapsed(object sender, EventArgs e)
{
//Do your stuffs here
}
If you use some delays smaller than the interval inside the timer, the system.timer will execute other thread and you have to deal with a double thread running at the same time. Apply an InvokeRequired to control the flow.
I would like to set a textbox text to "blink" by changing text colors when a button is clicked.
I can get the text to blink how I want it to, but I want it to stop after a few blinks. I cannot figure out how to make it stop after the timer fires a few times.
Here is my code:
public Form1()
{
InitializeComponent();
Timer timer = new Timer();
timer.Interval = 500;
timer.Enabled = false;
timer.Start();
timer.Tick += new EventHandler(timer_Tick);
if (timerint == 5)
timer.Stop();
}
private void timer_Tick(object sender, EventArgs e)
{
timerint += 1;
if (textBoxInvFooter.ForeColor == SystemColors.GrayText)
textBoxInvFooter.ForeColor = SystemColors.Highlight;
else
textBoxInvFooter.ForeColor = SystemColors.GrayText;
}
I know my problem lies with how I'm using the "timerint", but I'm not sure where to put it, or what solution I should use...
Thank you for all your help!
You just have to put the timer check inside the Tick handler. You can access the Timer object by using the sender argument of the handler.
private void timer_Tick(object sender, EventArgs e)
{
// ...
timerint += 1;
if (timerint == 5)
{
((Timer)sender).Stop();
}
}
Here's the complete code that I would use to solve your issue. It correctly stops the timer, detaches the event handler, and disposes the timer. It disables the button during the flashing, and also restores the colour of the textbox after the five flashes are complete.
The best part is that it is purely defined within the one lambda, so no class-level variables required.
Here it is:
button1.Click += (s, e) =>
{
button1.Enabled = false;
var counter = 0;
var timer = new Timer()
{
Interval = 500,
Enabled = false
};
EventHandler handler = null;
handler = (s2, e2) =>
{
if (++counter >= 5)
{
timer.Stop();
timer.Tick -= handler;
timer.Dispose();
textBoxInvFooter.ForeColor = SystemColors.WindowText;
button1.Enabled = true;
}
else
{
textBoxInvFooter.ForeColor =
textBoxInvFooter.ForeColor == SystemColors.GrayText
? SystemColors.Highlight
: SystemColors.GrayText;
}
};
timer.Tick += handler;
timer.Start();
};