Blazor: Building a Timer and a Stopwatch

taurius litvinavicius
5 min readJan 18, 2020

--

Timers are always useful, but at the same time always tricky. That tricky part usually comes with a problem when a background process needs to access (update) some user interface details. In WPF we use dispatcher, which is a difficult thing to do, in Blazor we use something similar, although one may say it is more straightforward.

Let us begin with a stopwatch example and see how everything gets updated.

stopwatch
code section for stopwatch page

The stopwatch itself is quite primitive, but the way it runs is a bit more advanced than just collecting form data and inserting into a database. We only use two variables — stopwatchvalue which holds the current time for the stopwatch, the other is a Boolean value is_stopwatchrunning for system to know if the stopwatch is active or not. The loop is active while the stopwatch is active and we have Task.Delay to wait 1 second before updating the value. There is a also an if statement and you will see why later. Also, notice how the extension method Add in the TimeSpan returns a new value, rather than updating the value inside the object. That is the reason why we have to assign the new value to the original variable.

Finally, the most important part is the StateHasChanged method. StopWatch method will be made to run in the background, so if you would not use StateHasChanged nothing in the UI would update. You can try this by simply commenting on the method and running the program — it will not work. In any background method, you should use this when the UI is updated at some point. You will see a more complex example when we get to the timer.

The interface itself is a bit more dynamic in this case. First, we have “Start” button which executes StopWatch task method without await keyword, meaning that it will run in the background and this is likely the easiest way to do it. Then, the “Pause” button simply sets is_stopwatchrunning to false, but does not void the TimeSpan value. The “Resume” button simply starts it again and since the value was not reset, it will continue from there. On the other hand, the “Stop” button stops it entirely, sets the value to false and then resets the TimeSpan value. Remember, previously we saw an if statement and this is why you need it. Because we have Task.Delay, chances are that when you click “Stop” button the cycle has already started and therefore if we do not check for the Boolean value it will add another second to the already reset variable.

Next we can get to a timer, in this we will also use TimeSpan, but it will start on initialization of the page. Similar technique is used in my classroom quiz Blazor example, which you find in various places (Links in resources).

A basic timer only really needs one variable — that in this case is TimeSpan, but it could also be an integer. In this case, we use Timer task method which contains a loop conditioned on TimeLeft (TimeSpan) being more than an empty one (0 seconds). Unlike the stopwatch, in this case we use Subtract method, because time is moving backwards in a timer. Once again, we need to use StateHasChanged method for UI to update. After the timer is at 0, we want to do something and we use AfterTime method which simply sets the displaytext variable. The important thing here is to use StateHasChanged after the AfterTime method as well. It does not matter if the variable is set in the background task itself or in the task executed in the background task, you still need to use that method to update the UI.

As you can see, doing something in Blazor is quite simple, but debugging in some cases — such as this one, is not reliable. If you run any of these wihout the StateHasChanged method, the UI will not updated, but it will also have no error, no exception will be thrown.

--

--