C# Blazor: Countdown Timer
Asked Answered
O

1

26

I'm new to C# and trying to create a simple countdown timer using System.Timer.Timers. It didn't work as expected and I searched the internet for a solution but it didn't really fix my problem. What I want is when the user clicks the start button, it begins and displays the countdown. But although the timer kinda worked, it didn't continuously display the timer when I clicked the button once, instead, I need to click the start button many times to see the countdown number or the timer display will not change. Here's the code.

@page "/"

<h1>Timer</h1>

<p>@counter</p>
<button @onclick="StartTimer">Start</button>


@code {
    private static System.Timers.Timer aTimer;
    private int counter = 60;
    public void StartTimer()
    {
        aTimer = new System.Timers.Timer(1000);
        aTimer.Elapsed += CountDownTimer;
        aTimer.Enabled = true;
    }

    public void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e)
    {
        if (counter > 0)
        {
            counter -= 1;
        }
        else
        {
            aTimer.Enabled = false;
        }
    }
}
Otten answered 12/11, 2020 at 2:34 Comment(1)
You are missing the Dispose() logic. A Timer is IDisposable.Arnettearney
P
32

Call StateHasChanged() when updating the counter so that the UI elements are updated.

Because your callback will run on a separate thread you will need to use InvokeAsync to call StateHasChanged().

public void CountDownTimer(Object source, ElapsedEventArgs e)
{
    if (counter > 0)
    {
        counter -= 1;
    }
    else
    {
        aTimer.Enabled = false;
    }
    InvokeAsync(StateHasChanged);
}
Procathedral answered 12/11, 2020 at 2:39 Comment(4)
Don't forget to Dispose() the Timer. Sample codeArnettearney
InvokeAsync(StateHasChanged) doesn't works, you shoud use InvokeAsync(() => StateHasChanged);Pyromania
@Payedmaunt do you have more information on your test scenario? The overload of InvokeAction used here takes an Action delegate, which has a signature of void () this matches the signature for StateHasChanges as well as the lambda you are passing. As it stands InvokeAsync(StateHasChanged) works, so there might be something you have different in your test case.Procathedral
InvokeAsync(StateHasChanged) definitely works, its the same as doing InvokeAsync(() => StateHasChanged) since StateHasChanged has no parametersDelta

© 2022 - 2024 — McMap. All rights reserved.