Blazored / Typeahead

Typeahead control for Blazor applications
https://blazored.github.io/Typeahead/
MIT License
447 stars 103 forks source link

[Bug] TaskCanceledException occured while doing "HookOutsideClick" #236

Open andrei-gubarev opened 3 years ago

andrei-gubarev commented 3 years ago

Describe the bug We are experiencing the following error:

System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Threading.Tasks.ValueTask<TResult>.get_Result()
   at Microsoft.JSInterop.JSRuntime+<InvokeWithDefaultCancellation>d__16<T>.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Blazored.Typeahead.BlazoredTypeahead<TItem, TValue>+<HookOutsideClick>d__164.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Blazored.Typeahead.BlazoredTypeahead<TItem, TValue>+<Search>d__163.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.Tasks.Task+<>c.<ThrowAsync>b__139_1(object state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

The exception is fatal for the Blazor server application since it doesn't have a proper global error handling mechanism until .NET 6 released. Exceptions can be handled with "try-catch" but not on external components like BlazoredTypeahead. I'm not sure exactly what's is causing the issue because it's very hard to reproduce. I think it's something about access to disposed and "closed" elements. Could you advise what's the best way to handle such errors? Or maybe you can add some global try-catch block to wrap the main component's logic.

Hosting Model (is this issue happening with a certain hosting model?): Blazor Server

andrei-gubarev commented 3 years ago

The same exception also occurred because of the error "Cannot access a disposed object. Object name: 'Timer'". Looks like it happens while trying to access "closed" component.

djukic-marko commented 6 months ago

Hello @andrei-gubarev. I'm experiencing the very same problem, and also with the timer. Did you manage to solve it, and what do you mean by a "closed" component? Since I'm kinda invested in this component, I tried to debug it, but I don't see a reason for this bug to occur.

I followed the stack trace to: await JSRuntime.OnOutsideClick(_searchInput, this, "ResetControlBlur", true);

But, I'm not 100% sure how to avoid it, other than putting it inside the Try/catch block.

: Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
:    at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
:    at Blazored.Typeahead.BlazoredTypeahead`2.HookOutsideClick()
:    at Blazored.Typeahead.BlazoredTypeahead`2.Search(Object source, ElapsedEventArgs e)
:    at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
:    at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
:    at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
:    at System.Threading.QueueUserWorkItemCallback.Execute()
:    at System.Threading.ThreadPoolWorkQueue.Dispatch()
:    at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
:    at System.Threading.Thread.StartCallback()
 Main process exited, code=killed, status=6/ABRT
 Failed with result 'signal'.
andrei-gubarev commented 6 months ago

Hi @djukic-marko !

I don't remember exactly as it was 4 years ago but I believe once .NET 6 was released, the exception was handled by ErrorBoundary https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/handle-errors?view=aspnetcore-8.0

And by the "closed" component I think I meant a state when the dropdown was collapsed.

I hope it helps!

djukic-marko commented 6 months ago

Hey @andrei-gubarev TBH, I didn't expect so swift response. Thanks for the idea about an ErrorBoundary, I will try to commit Try/Catch and check with @chrissainty if he will accept it and push a new version to Nuget. If not, I'll go with the ErrorBoundary solution. Thanks a lot!

Yeah, I guessed so about Typeahead, but what about Timer? You've put it inside ErrorBoundary also. I've written a SO question about that just a few days ago.

andrei-gubarev commented 6 months ago

If I remember correctly I was talking about Timer that is part of Typeahead component so I didn't have control over it.

djukic-marko commented 6 months ago

@andrei-gubarev OMG, I had a few timers in my app... Commented them out, and still getting exceptions about some timers. You are right, the source of the problem was the TypeAhead timer.