I am currently developing using blazor and I would like to check the status of a database item every 5 seconds, then update the UI when the status changes. When status is changed, I want it to stop querying for the item.
The bit I am struggling with is this:
protected override async Task<Task> OnAfterRenderAsync(bool firstRender)
{
// if status is still pending, start countdown again.
if (_ApplicationState.Item.Status == ItemStatus.PENDING)
{
Console.WriteLine(_ApplicationState.Item.Status " - Count again!");
TimerCount = 5;
StateUpdateCountdown();
}
return base.OnAfterRenderAsync(firstRender);
}
private void StateUpdateCountdown()
{
var timer = new Timer(_ =>
{
if (TimerCount > 0)
{
Console.WriteLine("Timer: " TimerCount);
TimerCount--;
}
else
{
// Fetch Item
_applcationState.Item = FetchItem(someId);
// Update State
InvokeAsync(StateHasChanged);
}
}, null, 1000, 1000);
}
So essentially, running a timer for 5 seconds, when timer hits 0, check item status. But when item status is no longer pending, it still tries to fetch the item. Is there an easier way of polling like this other than setting a timer?
I was looking at EventHandling in Blazor but im unsure what the best way for me to do this is.
CodePudding user response:
Your issue happens because you never stop timer
. Indeed, when TimerCount
becomes negative, you will always execute what is in the else
statement, which fetches the item.
In your case, you are recreating a Timer
on every render which is probably a bad idea since you do not control when Blazor is going to rerender. At least, stop the previous instances of the timer to avoid having multiple instances of Timer running simultaneously. You could create a variable timer on the razor page scope to control it easier.