i want to segue to a new View Controller when the countdown timer, here set to 10 seconds, reaches 0 seconds. it does this using the thread logic below. the label usually shows the countdown "10, 9, 8, 7" but since i used ViewDidAppear, it doesnt show. at the end itll flash 0 seconds, and the segue will take place. i need the countdown to show the whole time, and cant figure out how and why its dissapearing
using System.Timers;
using System.Threading;
...
private System.Timers.Timer mytimer;
private int countSeconds;
...
public override void ViewDidLoad()
{
base.ViewDidLoad();
mytimer = new System.Timers.Timer();
//Trigger event every second
mytimer.Interval = 1000; //1000 = 1 second
mytimer.Elapsed += OnTimedEvent;
countSeconds = 10; // 300 seconds
mytimer.Enabled = true;
mytimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
countSeconds--;
int seconds = countSeconds % 60;
int minutes = countSeconds / 60;
string DHCountdownTime = (countSeconds / 60).ToString() + ":" + (countSeconds % 60).ToString("00"); //to give leading 0. so 9 seconds isnt :9 but :09
InvokeOnMainThread(() =>
{
lblTimer.Text = DHCountdownTime;
});
if (countSeconds == 0)
{
mytimer.Stop();
}
}
...
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
Thread.Sleep(countSeconds * 1000);
PerformSegue("DHSegue", this);
...
Your Thread.Sleep is blocking the UI thread:
Thread.Sleep(countSeconds * 1000);
Use a task (or another thread) in order allow the UI thread to continue to process messages:
await Task.Delay(countSeconds * 1000);
Related
I'm trying to create a timed task program (think Reminders app for Apple but with timers), and I'm trying to implement the timer. The timer starts and the event works fine, but for some reason, the timer event gets called right after starting the timer, rather than after the specified interval. This is my code for setting the interval:
newTask.timerTime = float.Parse(timeInput.Text);
newTask.Initialize();
switch (timeInput.Text)
{
case "Seconds":
newTask.timer.Interval = (int)newTask.timerTime * 1000;
break;
case "Minutes":
newTask.timer.Interval = (int)(newTask.timerTime * 1000) * 60;
break;
case "Hours":
newTask.timer.Interval = (int)((newTask.timerTime * 1000) * 60) * 60;
break;
}
newTask.timer.Enabled = true;
newTask.timer.Start();
And this is my code for creating the event (and Timer.Tick):
public void Initialize()
{
timer.Tick += new System.EventHandler(OnTimerEnd);
}
//Timer event
private void OnTimerEnd(object sender, EventArgs e)
{
new ToastContentBuilder()
.AddArgument("action", "viewConversation")
.AddArgument("taskid", 1)
.AddText("Your timer is up!")
.AddText($#"Your task, {taskName}, is now completed! Great job!")
.Show();
timer.Stop();
timer.Enabled = false;
}
I have a method which does some calculations.
public void CalculateItems()
{
// Calculate the empty Items
}
Which I need to execute in every 30th second of a minute.
If my service starts at 10:00:15, The method should start working from 10:00:30, 10:01:00, 10:01:30 and goes on.
If my Service starts at 10:00:50, The method should start working from 10:01:00, 10:01:30, 10:02:00 and goes on.
I have tried System.Threading.Timer, System.Timers.Timer but in all these, I couldn't achieve my scenario. Please help with your valuable suggestions.
What I have tried is in System.Threading.Timer
var timer = new System.Threading.Timer(
e => CalculateItems(),
null,
TimeSpan.Zero,
TimeSpan.FromSeconds(30));
But it hits my method every 30th second Not in 30th second of every minute
One simple way to solve it using a timer is to set the interval to a single second, and in the timer's callback method to check if the value of DateTime.Now.Seconds divides by 30:
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(DateTime.Now.Seconds % 30 == 0)
{
CalculateItems();
}
}
You can initially start the timer with 1 second interval. Then in the Timer Event, if DateTime.Now.Second is 30 or 0, You can set the interval to 30 seconds. From then on your event would be triggered only at specified time.
System.Timers.Timer timer= new System.Timers.Timer(1000);
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
if(timer.Interval!=30000 && DateTime.Now.Seconds % 30 == 0)
{
timer.Stop();
timer.Interval = 30000;
timer.Start();
DoWork();
}
else
{
if(timer.Interval==30000)
{
DoWork();
}
}
}
I solved it with timers, and calculating the sime to the next 30 sec block:
It is recalculating the 30 sec again after elapsed, otherwise it will slightly get a delta after each run.
class Program
{
static System.Threading.Timer _ttimer;
static void Main(string[] args)
{
SetupTimerTo30sec();
Console.ReadLine();
}
private static void SetupTimerTo30sec()
{
var now = DateTime.Now;
int diffMilliseconds;
if (now.Second < 30)
{
diffMilliseconds = (30 - now.Second) * 1000;
}
else
{
diffMilliseconds = (60 - now.Second) * 1000;
}
diffMilliseconds -= now.Millisecond;
if (_ttimer != null)
{
_ttimer.Change(diffMilliseconds, 30 * 1000);
}
else
{
_ttimer = new Timer(OnElapsed, null, diffMilliseconds, 30 * 1000);
}
}
private static void OnElapsed(object state)
{
Console.Write(DateTime.Now.ToLongTimeString());
Console.WriteLine($":{DateTime.Now.Millisecond}");
SetupTimerTo30sec();
}
}
Here I have a code of an alarm clock:
public static void Main(string[] args)
{
Console.Write("Seconds: ");
int seconds = int.Parse(Console.ReadLine());
System.Threading.Thread.Sleep(seconds * 1000);
Timer timer = new Timer(100);
timer.Elapsed += MakeSound;
timer.Enabled = true;
GC.KeepAlive(timer);
Console.ReadLine();
}
private static void MakeSound(object sender, ElapsedEventArgs e)
{
Console.Beep();
}
As you can see, it doesn't look so promising because I am using Thread.Sleep.
It still works if I use
Timer timer = new Timer(seconds * 1000); instead of System.Threading.Thread.Sleep(seconds * 1000);
But it doesn't beep constantly, just between interval of seconds * 1000 seconds until user presses Enter. Can I make it any better?
If you look at the constructor overloads for System.Threading.Timer, you'll see that you can specify the dueTime, as well as the period: https://msdn.microsoft.com/en-us/library/2x96zfy7(v=vs.110).aspx
So, instead of using System.Threading.Thread.Sleep(1000 * seconds), use
Timer timer = new Timer(new TimerCallback(MakeSound), null, 1000 * seconds, 100);
How to stop a timer after some numbers of ticks or after, let's say, 3-4 seconds?
So I start a timer and I want after 10 ticks or after 2-3 seconds to stop automatically.
Thanks!
You can keep a counter like
int counter = 0;
then in every tick you increment it. After your limit you can stop timer then. Do this in your tick event
counter++;
if(counter ==10) //or whatever your limit is
yourtimer.Stop();
When the timer's specified interval is reached (after 3 seconds), timer1_Tick() event handler will be called and you could stop the timer within the event handler.
Timer timer1 = new Timer();
timer1.Interval = 3000;
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(timer1_Tick);
void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop(); // or timer1.Enabled = false;
}
i generally talking because you didn't mention which timer, but they all have ticks... so:
you'll need a counter in the class like
int count;
which you'll initialize in the start of your timer, and you'll need a dateTime like
DateTime start;
which you'll initialize in the start of your timer:
start = DateTime.Now;
and in your tick method you'll do:
if(count++ == 10 || (DateTime.Now - start).TotalSeconds > 2)
timer.stop()
here is a full example
public partial class meClass : Form
{
private System.Windows.Forms.Timer t;
private int count;
private DateTime start;
public meClass()
{
t = new Timer();
t.Interval = 50;
t.Tick += new EventHandler(t_Tick);
count = 0;
start = DateTime.Now;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
if (count++ >= 10 || (DateTime.Now - start).TotalSeconds > 10)
{
t.Stop();
}
// do your stuff
}
}
Assuming you are using the System.Windows.Forms.Tick. You can keep track of a counter, and the time it lives like so. Its a nice way to use the Tag property of a timer.
This makes it reusable for other timers and keeps your code generic, instead of using a globally defined int counter for each timer.
this code is quiet generic as you can assign this event handler to manage the time it lives, and another event handler to handle the specific actions the timer was created for.
System.Windows.Forms.Timer ExampleTimer = new System.Windows.Forms.Timer();
ExampleTimer.Tag = new CustomTimerStruct
{
Counter = 0,
StartDateTime = DateTime.Now,
MaximumSecondsToLive = 10,
MaximumTicksToLive = 4
};
//Note the order of assigning the handlers. As this is the order they are executed.
ExampleTimer.Tick += Generic_Tick;
ExampleTimer.Tick += Work_Tick;
ExampleTimer.Interval = 1;
ExampleTimer.Start();
public struct CustomTimerStruct
{
public uint Counter;
public DateTime StartDateTime;
public uint MaximumSecondsToLive;
public uint MaximumTicksToLive;
}
void Generic_Tick(object sender, EventArgs e)
{
System.Windows.Forms.Timer thisTimer = sender as System.Windows.Forms.Timer;
CustomTimerStruct TimerInfo = (CustomTimerStruct)thisTimer.Tag;
TimerInfo.Counter++;
//Stop the timer based on its number of ticks
if (TimerInfo.Counter > TimerInfo.MaximumTicksToLive) thisTimer.Stop();
//Stops the timer based on the time its alive
if (DateTime.Now.Subtract(TimerInfo.StartDateTime).TotalSeconds > TimerInfo.MaximumSecondsToLive) thisTimer.Stop();
}
void Work_Tick(object sender, EventArgs e)
{
//Do work specifically for this timer
}
When initializing your timer set a tag value to 0 (zero).
tmrAutoStop.Tag = 0;
Then, with every tick add one...
tmrAutoStop.Tag = int.Parse(tmrAutoStop.Tag.ToString()) + 1;
and check if it reached your desired number:
if (int.Parse(tmrAutoStop.Tag.ToString()) >= 10)
{
//do timer cleanup
}
Use this same technique to alternate the timer associated event:
if (int.Parse(tmrAutoStop.Tag.ToString()) % 2 == 0)
{
//do something...
}
else
{
//do something else...
}
To check elapsed time (in seconds):
int m = int.Parse(tmrAutoStop.Tag.ToString()) * (1000 / tmrAutoStop.Interval);
so, i want this: if specific time passed (for example 9 hours) from loading form, than i want to show messagebox said "9 hours passed". my code is this:
public partial class Form1 : Form
{
Stopwatch stopWatch = new Stopwatch();
public Form1()
{
InitializeComponent();
stopWatch.Start();
}
private void button1_Click(object sender, EventArgs e)
{
double sec = stopWatch.ElapsedMilliseconds / 1000;
double min = sec / 60;
double hour = min / 60;
if (hour == 9.00D)
{
stopWatch.Stop();
MessageBox.Show("passed: " + hour.ToString("0.00"));
}
}
}
and the problem is that i don't know where to write this part of code:
if (hour == 9.00D)
{
stopWatch.Stop();
MessageBox.Show("passed: " + hour.ToString("0.00"));
}
so, where i write this code? if you have better way of doing this, please show me.
In addition to using a Timer as outlined by the others, you can directly use the TotalHours() property of the TimeSpan returned by Stopwatch.Elapsed:
TimeSpan ts = stopWatch.Elapsed;
if (ts.TotalHours >= 9)
{
MessageBox.Show("passed: " + ts.TotalHours.ToString("0.00"));
}
What people are not appreciating is that it is very unlikely that the double hours will be exactly 9.00! Why not just ask your timer to fire once, after the time you want, 9 hours.
Timer timer;
public Form1()
{
InitializeComponent();
timer.Tick += timer_Tick;
timer.Interval = TimeSpan.FromHours(9).TotalMilliseconds;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
MessageBox.Show("9 hours passed");
}
In order to do a specific task after a specific period of time System.Forms.Timer should be used (in case of windows forms). You can use its Elapsed event and in that you can implement your conditions.
Try using Timer instead. Example from here
Timer timer;
public Form1()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick); // when timer ticks, timer_Tick will be called
timer.Interval = (1000) * (10); // Timer will tick every 10 seconds
timer.Enabled = true; // Enable the timer
timer.Start(); // Start the timer
}
void timer_Tick(object sender, EventArgs e)
{
double sec = stopWatch.ElapsedMilliseconds / 1000;
double min = sec / 60;
double hour = min / 60;
if (hour == 9.00D)
{
stopWatch.Stop();
MessageBox.Show("passed: " + hour.ToString("0.00"));
}
}
Use Timer:
Timer regularly invokes code. Every several seconds or minutes, it
executes a method. This is useful for monitoring the health of an
important program, as with diagnostics. The System.Timers namespace
proves useful.
see this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
stopWatch.Start();
tm.Interval = 1000;
tm.Enabled = true;
tm.Tick += new EventHandler(tm_Tick);
tm.Start();
}
void tm_Tick(object sender, EventArgs e)
{
double sec = stopWatch.ElapsedMilliseconds / 1000;
double min = sec / 60;
double hour = min / 60;
if (hour == 9.00D)
{
stopWatch.Stop();
MessageBox.Show("passed: " + hour.ToString("0.00"));
}
}
}