C# - Update UI on Timer tick while delaying based on Timer value - c#

I want my WPF application to display a 3-second countdown before displaying an image, using a timer to display the "3, 2, 1" count based on the elapsed three seconds (meaning use the timer to update the UI) while waiting to display the image until the three seconds have elapsed (meaning have the method wait).
In pseudocode, I am trying to do the following:
3 is displayed, then one second elapses
2 is displayed, then one second elapses
1 is displayed, then one second elapses
The image is displayed
I am trying to use a System.Timers.Timer, such as:
...
public int Countdown = 3;
...
private void UpdateCountdown(object source, EventArgs e)
{
Countdown--;
}
public void DoStuff()
{
Timer timer = new Timer();
timer.Interval = 1000;
timer.Elapsed += UpdateCountdown;
timer.Start();
while (Countdown > 0)
{
// do not act until the 3 seconds have elapsed
}
// now that 3 seconds have elapsed...
ShowImage();
}
and in my xaml, I am binding the Countdown value to a TextBlock:
<TextBlock Name="TbCountdown" Text="{Binding Path=Countdown}"/>
I have tried a few different things, such as trying Dispatcher.Invoke. My problem is that one of the two following things always happens:
The UI gets blocked and does not show 3 turn into 2, etc.
The UI shows the 3, 2, 1 correctly but the ShowImage() method does not wait for the 3 seconds, it just happens instantly.
Any advice?

Don't busy spin on the Countdown value in DoStuff, rather put the test and ShowImage() in the UpdateCountdown handler.
private void UpdateCountdown(object source, EventArgs e)
{
if (--Countdown == 0)
ShowImage();
}
public void DoStuff()
{
Timer timer = new Timer();
timer.Interval = 1000;
timer.Elapsed += UpdateCountdown;
timer.Start();
}

Related

How do I trigger an event X seconds after a button has been clicked in a Xamarian iOS application?

I am teaching myself C# and, as part of this, am trying to develop an iOS countdown timer app that is to play a .wav sound file X seconds after a timer initiating button has been clicked as the timer value has gone from X to 0.
In an attempt to do this I have tried using the System.Timers namespace but have been unable to figure out how to program the countdown timer described above. Below is my incomplete code (code that obviously does not fulfill the above described function but might be a part of the full code that would fulfill that function):
partial void UIButton1416_TouchUpInside(UIButton sender)
{
url = NSUrl.FromFilename("Sounds/bell.wav");
bell = new SystemSound(url);
int RoundedTimerValue = Convert.ToInt32(Math.Round(TimerSlider.Value, 0));
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 60000;
timer.Enabled = true;
}
Does anyone know how to create the described countdown timer / Trigger an event X seconds after a button has been clicked?
Example Code.
Timer timer = new Timer();
timer.Interval = 60000;
timer.Elapsed += new ElapsedEventHandler((x,y) => {
//Do whatever you want
timer.Stop();
});
Put the below code in the Button Click Handler and make the timer variable global.
timer.Start();
Or you can leave everything in the Button's click handler, not a big deal.
Explanation:
The timer class has an event called Elapsed which is called when the specified number of milliseconds in the timer's Interval gets over. with the line
timer.Elapsed += new ElapsedEventHandler((x,y) => {...
we are assigning a Delegate(Virtual function) to be called when the timer is up. therefore any code within the braces{} will be called at every Timer.Interval milliseconds. we stop the timer at that time as we don't want it to keep running and generate a lot of events.
Update 2:
Normally , EventHandlers are Defined using
return_type functionName(object sender, EventArgs e);
But since the delegate is virtual, so is the parameter. x corresponds to sender and y corresponds to e.
that event handler code can also be written as below
void someFunction(object sender, ElapsedEventArgs e)
{
timer.Stop();
}
and then,
timer.Elapsed += new ElapsedEventHandler(someFunction);
As for the '=>' you can read about Lambda Expressions Here

Extend the timer duration while ticking

I have a windows form application with time input(in minutes) which fires a GUI application after the timer elapses. Initially I take the input from the user and set the time. Say, the user enters 45 mins. After 45 mins, my other GUI application is launched. Currently I'm using this:
Timer MyTimer = new Timer();
private void Form1_Load(object sender, EventArgs e)
{
MyTimer.Interval = 45mins // Input from user
MyTimer.Tick += new EventHandler(MyTimer_Tick);
MyTimer.Start();
}
private void MyTimer_Tick(object sender, EventArgs e)
{
//pop my GUI application
}
so now, my question is, how can i extended the timer? Suppose while counting down in the 20th Minute, the user wishes to extend 15mins of the timer, i take the input as 15 from the user and after that, the timer should add this 15 mins to the existing time and fire the GUI app after 35mins. i.e, it should count from 35mins.In total after the time elapses, it would have been 50mins. How can I achieve this?
Actually setting the timer to 1 second is just fine. there will be no performance hit. just keep track of the DateTime when it started, then you can use the tick event to display the elapsed time and check if that duration is greater than what the user wants
private DateTime timerStart;
private TimeSpan duration;
private void Form1_Load(object sender, EventArgs e)
{
Timer MyTimer = new Timer();
MyTimer.Interval = 1000; // tick at one second to update the UI
MyTimer.Tick += new EventHandler(MyTimer_Tick);
duration = whatever...// Input from user
timerStart = DateTime.Now;
MyTimer.Start();
}
private void changeTimer(TimeSpan newValue) {
duration = newValue;
}
private void MyTimer_Tick(object sender, EventArgs e)
{
TimeSpan alreadyElapsed = DateTime.Now.Subtract(timerStart);
// update the UI here using the alreadyElapsed TimeSpan
if(alreadyElapsed > duration)
{
//pop my GUI application
}
}
That's easy to implement if you set your timer to a one second/minute interval and another variable to the number of seconds/minutes.
Decrease the variable value on each timer tick. Add to that variable if you need to expand the interval. If the variable value is 0,launch the other application.

How to countdown in seconds from minutes using a countdown timer

Currently developing a simple windows phone 8.1 silverlight app with an implemented countdown time. I have it working where I can input a set amount of minutes and it countdowns fine but what I am wanting to happen is for a user to input an amount of minutes and to countdown in seconds from there, for example it is currently 10, 9, 8, 7, 6, 5 when 10 seconds is input.
What I want to happen is that the user inputs 5 and it counts down like so:
4:59
4:58
4:57
This is my current code:
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += timer_Tick;
basetime = Convert.ToInt32(tbxTime.Text);;
tbxTime.Text = basetime.ToString();
timer.Start();
}
void timer_Tick(object sender, object e)
{
basetime = basetime - 1;
tbxTime.Text = basetime.ToString();
if (basetime == 0)
{
timer.Stop();
}
You can keep most of your existing code if you just make basetime a TimeSpan instead of an int. It's easy to set its value from Minutes or Seconds via the appropriate static method.
var basetime = TimeSpan.FromMinutes(5);
Then you can subtract one second from it like this:
basetime -= TimeSpan.FromSeconds(1);
And display it like this:
tbxTime.Text = basetime.ToString(#"m\:ss");
Finally, comparing it to zero is also trivial:
if (basetime <= TimeSpan.Zero)
See Custom TimeSpan Format Strings for more display options.
I think you can just make use of suitable formatting of TimeSpan class (you will surely find many examples on SO). The easy example can look like this (I assume that you have a TextBox where you enter time and TextBlock which shows counter);
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
TimeSpan time;
public MainPage()
{
this.InitializeComponent();
timer.Tick += (sender, e) =>
{
time -= TimeSpan.FromSeconds(1);
if (time <= TimeSpan.Zero) timer.Stop();
myTextBlock.Text = time.ToString(#"mm\:ss");
};
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{ time = TimeSpan.FromMinutes(int.Parse((sender as TextBox).Text)); }
private void startBtn_Click(object sender, RoutedEventArgs e)
{ timer.Start(); }
Note that this is a very simple example. You should also think if DispatcherTimer is a good idea - it works on dispatcher, so in case you have some big job running on main UI thread it may not count the time properly. In this case you may think of using different timer, for example System.Threading.Timer, this runs on separate thread, so you will have to update your UI through Dispatcher.

Delay windows 8 app countdown timer c#

I have a windows 8 game app that uses a timer for each level and I am trying to the timer 3 seconds.
The code I have to start the timer works but I can't seem to delay the timer so that I display words to count it down.
Here is the code:
private async void timer_Tick(object sender, object e)
{
await
Time.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low,
() =>
{ Time.Text = string.Format("{0}:{1}", (Counter/60), (Counter%60).ToString().PadLeft(2, ' ')); });
Counter--;
await Task.Delay(3000);}}
so I put async there because I thought I should put await Task.Delay(3000); after counter to delay the timer but it doesn't work. I do not want to the WinRT Xaml toolkit countdown timer because I don't want the animation there.
Any suggestions on what I am doing wrong would be great!
So presumably you want to update the display every second, to get this countdown? But if I've understood, for some reason you want to delay everything by 3 seconds.
If you want things to happen 3 seconds later than they're currently happening, the obvious solution is to program the timer so it calls you when you actually want it to:
private DispatcherTimer t = new DispatcherTimer();
private int Counter = 120;
public MainPage()
{
InitializeComponent();
t.Interval = TimeSpan.FromSeconds(4);
t.Tick += timer_Tick;
t.Start();
}
private void timer_Tick(object sender, object o)
{
t.Interval = TimeSpan.FromSeconds(1);
Time.Text = string.Format("{0}:{1}", (Counter / 60), (Counter % 60).ToString().PadLeft(2, ' '));
Counter--;
}
That makes the first tick take 4 seconds to arrive, and then adjusts the interval to 1 second. So you'll get ticks spaced at 1 second intervals, but everything will happen 3 seconds later than it otherwise would. (If set the tick interval to 1 initially, then the first tick would take 1 second to arrive, which is why you need a delay of 4 seconds initially - an initial tick of 3 would only delay things by 2 seconds.)
However, if you need to do some things immediately, and some with a delay, one obvious way to do that would be just to adjust the count in your handler by 3 seconds:
private const int LevelMaxTime = 120;
private DispatcherTimer t = new DispatcherTimer();
private int Counter = LevelMaxTime;
public MainPage()
{
InitializeComponent();
t.Interval = TimeSpan.FromSeconds(1);
t.Tick += timer_Tick;
t.Start();
}
private void timer_Tick(object sender, object o)
{
// Do the undelayed work here, whatever that is...
// Next, we do the delayed work, if there is any yet.
int effectiveCount = Counter + 3;
if (effectiveCount <= LevelMaxTime)
{
Time.Text = string.Format("{0}:{1}", (effectiveCount / 60), (effectiveCount % 60).ToString().PadLeft(2, ' '));
}
Counter--;
}
This just takes the effective current time to be 3 seconds before what Current says it is, thus delaying everything by 3 seconds.
You could do something more like your original code:
private async void timer_Tick(object sender, object o)
{
// Wait for 3 seconds...for some reason
await Task.Delay(TimeSpan.FromSeconds(3));
Time.Text = string.Format("{0}:{1}", (Counter / 60), (Counter % 60).ToString().PadLeft(2, ' '));
Counter--;
}
That's closer in spirit to what you wrote (as far as I can tell), only it works, but it seems unnecessarily convoluted. Why not just program the timer to call you at the right time, rather than getting callbacks at the wrong time and then trying to compensate? It's a timer. It'll call you when you tell it to!

How to delay a method in C# for Windows Phone 7?

I have a method.
public bool bBIntersectsBT(Rect barTopTipRect, Rect barBottomTipRect, Rect blueBallRect)
{
barTopTipRect.Intersect(blueBallRect);
barBottomTipRect.Intersect(blueBallRect);
if (barTopTipRect.IsEmpty && barBottomTipRect.IsEmpty)
{
return false;
}
else
{
return true;
}
}
I want to delay this method for 2 seconds before this method is executed again. I have read up about Thread.Sleep, However, that is not what I want. I do not want the program to pause and resume it.
Use a DispatcherTimer:
DispatcherTimer timer = new DispatcherTimer();
//TimeSpan is in format: Days, hours, minutes, seconds, milliseconds.
timer.Interval = new TimeSpan(0, 0, 0, 2);
timer.Tick += timerTick;
timer.Start();
private void timerTick(Object sender, EventArgs e)
{
//Your code you want to execute every 2 seconds
//If you want to stop after the two seconds just add timer.Stop() here
}
You can user Dispatch Timer to achieve your goal. Set it to 2 seconds when you want. And after you are done with it. you can stop it.

Categories

Resources