I am using a timer to run a method every 16 minutes. I also want to run a second method every minute for 15 minutes in-between.
Below is the code I am using:
int count = 0;
private void cmdGo_Click(object sender, EventArgs e)
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 960000; // specify interval time - 16 mins
t.Tick += new EventHandler(timer_Tick);
t.Start();
}
void timer_Tick(object sender, EventArgs e)
{
RunMethod1();
while(count < 15)
{
//waiting for 60 seconds
DateTime wait = DateTime.Now;
do
{
Application.DoEvents();
} while (wait.AddSeconds(60) > DateTime.Now);
RunMethod2();
}
}
The above code seems to work fine but the ‘do while’ loop to wait for 60 seconds is very CPU heavy.
I tried to use Thread.Sleep(60000) but this freezes up the Interface and also tried to add a second timer within timer_Tick but this doesn’t seem possible. Can a second timer be added within the EventHandler of the first?
Is there any other method to achieve this without being so CPU intensive?
Thanks!
Warren
NOTE: Sorry guys, there was a typo in my original post. The 60 second wait do, while loop should have been within the while < 15 loop. Just updated the code snippet.
So:
RunMethod1() should be executed every 16 mins
RunMethod2() should be executed every 1 min (15 times) in between the 16 min tick
It would make more sense to have a counter to store how many times the clock has gone off. Then set your timer interval to fire once a minute so not doing anything in between...
That way you could just do...
private int Counter;
private void cmdGo_Click(object sender, EventArgs e)
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 60000; // specify interval time - 1 minute
t.Tick += new EventHandler(timer_Tick);
t.Start();
}
// Every 1 min this timer fires...
void timer_Tick(object sender, EventArgs e)
{
// If it has been 16 minutes then run RunMethod1
if (++Counter >= 16)
{
Counter = 0;
RunMethod1();
return;
}
// Not yet been 16 minutes so just run RunMethod2
RunMethod2();
}
You could await a task Delay so the UI will keep responding
async void timer_Tick(object sender, EventArgs e)
{
RunMethod1();
while (count < 15)
{
//waiting for 60 seconds
await Task.Delay(60000);
RunMethod2();
}
}
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 followed an example from Head First C# on DispatcherTimer.
First time I press the button the ticker will increase by 1 second, but the next time I click on the button the ticker will increase by 2 seconds for every second/tick. Third time ticker increases with 3 seconds and so on (1 second is added for every button press).
Why is that and how to i "reset" the ticker Interval so it will only increase by 1 second every time?
Here is code:
DispatcherTimer timer = new DispatcherTimer();
private void Button_Click_1(object sender, RoutedEventArgs e)
{
timer.Tick += timer_Tick;
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Start();
CheckHappiness();
}
int i = 0;
void timer_Tick(object sender, object e)
{
ticker.Text = "Tick #" + i++;
}
private async void CheckHappiness()
{
... code ..
timer.Stop();
}
}
}
Cheers!
timer.Tick += timer_Tick;
This line adds the method to the eventhandler everytime you press the button; in which you do an i++ which increases i by one.
When you have two methods doing that at the same time (since the timer ticks on your interval) then you get an increase by two every tick of the timer.
My program has a parameter that starts up the winform and waits x number of seconds before it runs a function. Currently I am using Thread Sleep for x seconds and then the function runs. how can I add a timer in the strip status label?
so that it says: x Seconds Remaining...
Instead of blocking thread execution, simply call your method when required timeout passes. Place new Timer to your form, and set it's Interval to 1000. Then subscribe to timer's Tick event and calculate elapsed time in event handler:
private int secondsToWait = 42;
private DateTime startTime;
private void button_Click(object sender, EventArgs e)
{
timer.Start(); // start timer (you can do it on form load, if you need)
startTime = DateTime.Now; // and remember start time
}
private void timer_Tick(object sender, EventArgs e)
{
int elapsedSeconds = (int)(DateTime.Now - startTime).TotalSeconds;
int remainingSeconds = secondsToWait - elapsedSeconds;
if (remainingSeconds <= 0)
{
// run your function
timer.Stop();
}
toolStripStatusLabel.Text =
String.Format("{0} seconds remaining...", remainingSeconds);
}
You can use a Timer:
public class Form1 : Form {
public Form1(){
InitializeComponent();
t = new Timer {Interval = 1000};
t.Tick += Tick;
//try counting down the time
CountDown(100);
}
DateTime start;
Timer t;
long s;
public void CountDown(long seconds){
start = DateTime.Now;
s = seconds;
t.Start();
}
private void Tick(object sender, EventArgs e){
long remainingSeconds = s - (DateTime.Now - start).TotalSeconds;
if(remainingSeconds <= 0) {
t.Stop();
toolStripStatusLabel1.Text = "Done!";
return;
}
toolStripStatusLabel1.Text = string.Format("{0} seconds remaining...", remainingSeconds);
}
}
I am making a program which has to check a data base once on every 30 or 60 minutes and display the results, if there are any, in the windows form interface. Of course, the other functions which the from provides access to, should still be usable while the data base check is being executed. To this end, I am using System.Timers.Timer which executes a method on a different thread from the UI one (If there is something wrong with using this approach, please feel free to comment on it). I wrote a small and simple program in order to test hot things work, only to notice that I cant really set the Interval to over ~ 1 minute ( I need 30 minutes to an hour). I came up with this solution:
public partial class Form1 : Form
{
int s = 2;
int counter = 1; //minutes counter
System.Timers.Timer t;
public Form1()
{
InitializeComponent();
t = new System.Timers.Timer();
t.Elapsed += timerElapsed;
t.Interval = 60000;
t.Start();
listBox1.Items.Add(DateTime.Now.ToString());
}
//doing stuff on a worker thread
public void timerElapsed(object sender, EventArgs e)
{
//check of 30 minutes have passed
if (counter < 30)
{
//increment counter and leave method
counter++;
return;
}
else
{
//do the stuff
s++;
string result = s + " " + DateTime.Now.ToString() + Thread.CurrentThread.ManagedThreadId.ToString();
//pass the result to the form`s listbox
Action action = () => listBox2.Items.Add(result);
this.Invoke(action);
//reset minutes counter
counter = 0;
}
}
//do other stuff to check if threadid`s are different
//and if the threads work simultaneously
private void button1_Click(object sender, EventArgs e)
{
for (int v = 0; v <= 100; v++)
{
string name = v + " " + Thread.CurrentThread.ManagedThreadId.ToString() +
" " + DateTime.Now.ToString(); ;
listBox1.Items.Add(name);
Thread.Sleep(1000); //so the whole operation should take around 100 seconds
}
}
}
But this way, the Elapsed event is being raised and the timerElapsed method called once every minute, it seems kinda useless. Is there a way to actually set longer timer interval ?
Interval is in miliseconds,so it seems that you've set your interval for 60 seconds:
t.Interval = 60000; // 60 * 1000 (1 minute)
If you want to have 1 hour interval then you need to change your interval to:
t.Interval = 3600000; // 60 * 60 * 1000 (1 hour)
I'm trying to create a Windows Form application that searches for a string and has three possible scenarios:
String 1 found - wait
String 2 found - stop
Else - Perform action and wait 1 minute
I am encountering my problem only on the times when it is expected to wait. When this happens, the newTimer_Tick starts to tick every second. I have tried disabling the timer when it ticks and a few other things but none appeared to work. Below is the code:
public void Action(string result)
{
if (result.Contains("string1"))
{
// Check again in 10 + x seconds
int n = new Random().Next(0, 5000);
int newtime = 10000 + n;
newTimer.Tick += new EventHandler(newTimer_Tick);
newTimer.Interval = newtime;
newTimer.Enabled = true;
}
else if (result.Contains("string2"))
{
// Turn off
newTimer.Enabled = false;
}
else
{
// Perform action and tick again in 1min + x seconds
action1();
int n = new Random().Next(0, 5000);
int newtime = 600000 + n;
newTimer.Tick += new EventHandler(newTimer_Tick);
newTimer.Interval = newtime;
newTimer.Enabled = true;
}
}
private void newTimer_Tick(object sender, EventArgs e)
{
Action( result );
}
What have I done wrong?
Each time the following line is called, an new instance of the event handler newTimerTick is added to the invocation list for the Tick event:
newTimer.Tick += new System.EventHandler(newTimer_Tick);
So every time the time tick goes off newTimerTick is going to be called multiple times, which is going to give you unexpected results.
Configure your event handler once only. In the constructor would be a sensible place.
Have you tried to stop the timer with the Timer.Stop method?
Btw: I don't think you need to reassign the Tick event from the newTimer unless you don't create a new Timer everytime.
I think what you were missing is that you have to stop your timer since you don't actually want it to keep for more than one interval. You seem to want to run it once, check on the result and then decide if you want to keep running it or not. Here's the code:
public void action(string result)
{
int n = new Random().Next(0, 5000);
Boolean blActivateTimer = true;
Timer timer = new Timer();
timer.Tick += timer_Tick;
if (!result.Contains("string1") && !result.Contains("string2"))
{
n += 600000;
action1();
}
else
{
if (result.Contains("string1"))
{
n += 10000;
}
else
{
blActivateTimer = false;
}
}
if (blActivateTimer)
{
timer.Start();
}
}
void action1()
{
}
void timer_Tick(object sender, EventArgs e)
{
Timer t = (Timer)sender;
t.Stop();
action(result);
}