I use Timer in the main components of our app. It’s used to trigger an endpoint every few minutes to tell us that the user is active on the application.
The code looks like this inside MainLayout.razor:
@implements IDisposable
.
.
.
private System.Threading.Timer Timer ;
protected override void OnInitialized()
{
Timer = new System.Threading.Timer(_ =>
{
if (applicationUser.LogedIn)
{
InvokeAsync(updateLastSeen);
}
}, null, 240000, 240000);
}
void IDisposable.Dispose()
{
Timer ?.Dispose();
Timer = null;
}
This works most of the time, but we sometimes see this exception. This results in application restart.
warn: Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer[100]
Unhandled exception rendering component: Cannot access a disposed object.
Object name: 'Timer'.
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Timer'.
at System.Timers.Timer.set_Enabled(Boolean value)
at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass32_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
Unhandled exception in circuit 'wO6hOy44Wd0kK3zpgb5w4E-9Frulb4mArReLXZ89NkI'.
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Timer'.
at System.Timers.Timer.set_Enabled(Boolean value)
at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass32_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
As far as I can see, we followed instructions from the docs.
Does anyone have an idea about the source of the problem here?