Added the process to update the data every second in Blazor Server.
This works fine, but when I press refresh page (F5) in my browser I get the following error:
System.ObjectDisposedException: 'Cannot process pending renders after the renderer has been disposed.
ObjectDisposed_ObjectName_Name'
The target code is here
@code {
private List<Models.Recipe> recipes { get; set; }
private List<Models.NowOrder> nowOrders { get; set; }
private List<Models.PlanOrder> planOrders { get; set; }
System.Threading.Timer _timer;
protected override void OnInitialized()
{
using (var dbContext = DbFactory.CreateDbContext())
{
this.recipes = dbContext.Recipes.ToList();
this.planOrders = dbContext.PlanOrders.ToList();
this.nowOrders = dbContext.NowOrders.ToList();
}
_timer = new System.Threading.Timer(async (_) =>
{
Time = DateTime.Now.ToString();
databaseValue = await TimerProcessGetValue();
await InvokeAsync(StateHasChanged);
}, null, 0, 1000);
}
public void Dispose()
{
_timer?.Dispose();
}
public async Task<int?> TimerProcessGetValue()
{
int? timerProcessValue;
using (var dbContext = DbFactory.CreateDbContext())
{
timerProcessValue = (await dbContext.TestTable.SingleAsync(x => x.Id == 1)).TestValue;
}
return timerProcessValue;
}
}
When refreshing the page "await InvokeAsync(StateHasChanged);"
If you comment out the following part, you will not get an error even if you press the F5 key, so I think that my handling of asynchronous processing is wrong, but I am troubled because I can not find the same case even if I search for the error I am.
What do you think is the cause of this? Thank you for your cooperation.
_timer = new System.Threading.Timer(async (_) =>
{
Time = DateTime.Now.ToString();
databaseValue = await TimerProcessGetValue();
await InvokeAsync(StateHasChanged);
}, null, 0, 1000);
Change to verification code
_timer = new System.Threading.Timer(async (_) =>
{
Time = DateTime.Now.ToString();
//databaseValue = await TimerProcessGetValue();
await Task.Delay(500); //Added verification code.
await InvokeAsync(StateHasChanged);
}, null, 0, 1000);
}
Append.(10/10/2021)
Version used: net core 5.0.7.
Browser used: Edge.
I'm not using any other browser.
My environment is limited and I can only use Edge ...
Below are the three codes we have verified.
①This is an example using Dispose (WaitHandle).
This did not improve the error.
public void Dispose()
{
using(System.Threading.WaitHandle waitHandle = new System.Threading.ManualResetEvent(false))
{
if (_timer.Dispose(waitHandle))
{
const int millisecondsTimeout = 500;
if (!waitHandle.WaitOne(millisecondsTimeout))
{
System.Diagnostics.Debug.WriteLine("Dispose Test");
}
}
}
}
②This is an example using System.Timers.Timer.
the reload using the F5 key was successful.
private int currentCount = 0;
private Timer timer2 = new(1000);
protected override void OnInitialized()
{
timer2.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer2.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
Time = DateTime.Now.ToString();
databaseValue = TimerProcessGetValue().Result;
StateHasChanged();
});
}
public void Dispose() => timer2.Dispose();
③Added error handling.
Even with this method, I succeeded in reloading with the F5 key without any error.
try
{
_timer = new System.Threading.Timer(async (_) =>
{
Time = DateTime.Now.ToString();
databaseValue = await TimerProcessGetValue();
await InvokeAsync(StateHasChanged);
}, null, 0, 1000);
}
catch
{
// empty on purpose
}