I've implemented a cancellable search in blazor. To illustrate:
When the user types multiple times, the previous search will be cancelled. This is achieved by using a cancellation token.
private bool _isLoading = false;
private CancellationTokenSource _cancellationTokenSrc;
public Func<string, CancellationToken, Task<IEnumerable<T>>> SearchFuncWithCancel { get; set; }
private void CancelToken()
{
try
{
_cancellationTokenSrc?.Cancel();
}
catch
{ }
_cancellationTokenSrc = new CancellationTokenSource();
}
private async Task OnSearchAsync()
{
IEnumerable<T> searched_items = Array.Empty<T>();
CancelToken();
try
{
_isLoading = true;
searched_items = (await SearchFuncWithCancel(Text, _cancellationTokenSrc.Token)) ?? Array.Empty<T>();
}
catch (Exception e)
{
Console.WriteLine("The search function failed to return results: " + e.Message);
}
finally
{
_isLoading = false;
}
//...
}
I am experiencing an issue with the code, where _isLoading is always false for a subsequent search. You can see it in the gif. The loading indicator is displayed the very first time. After that it does not show up anymore.
When a search gets cancelled due to another search the SearchFuncWithCancel method will exit and the finally block will be called. This sets _isLoading to false, while the other search is still awaiting results.
Any ideas how to fix that? My first idea was to use a stack. Whenever search is invoked, we push a true onto the stack. In the finally block we pop from the stack. As long as there is something on the stack, _isLoading must be true. Not sure if that is the best solution for this problem.
