gpt4 book ai didi

c# - 更新页面时 Blazor Server System.ObjectDisposedException 问题

转载 作者:行者123 更新时间:2023-12-05 02:38:38 25 4
gpt4 key购买 nike

添加了在 Blazor Server 中每秒更新数据的过程。

这工作正常,但是当我在浏览器中按刷新页面 (F5) 时,出现以下错误:

System.ObjectDisposedException: 'Cannot process pending renders after the renderer has been disposed.
ObjectDisposed_ObjectName_Name'

目标代码在这里

@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;
}
}

刷新页面时“await InvokeAsync(StateHasChanged);”

如果注释掉下面的部分,即使按F5键也不会出错,所以我认为我对异步处理的处理是错误的,但我很苦恼,因为我什至找不到相同的情况如果我搜索我的错误。

您认为造成这种情况的原因是什么?感谢您的合作。

_timer = new System.Threading.Timer(async (_) =>
{
Time = DateTime.Now.ToString();
databaseValue = await TimerProcessGetValue();
await InvokeAsync(StateHasChanged);
}, null, 0, 1000);

修改验证码

        _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);
}

追加。(10/10/2021)

使用的版本:net core 5.0.7。

使用的浏览器:Edge。

我没有使用任何其他浏览器。

我的环境有限,只能用Edge ...

以下是我们验证过的三个代码。

①这是一个使用Dispose(WaitHandle)的例子。

这并没有改善错误。

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");
}
}
}
}

②这是一个使用System.Timers.Timer的例子。

使用 F5 键重新加载成功。

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();

③添加了错误处理。

即使使用这种方法,我也成功地使用 F5 键重新加载,没有任何错误。

    try
{
_timer = new System.Threading.Timer(async (_) =>
{
Time = DateTime.Now.ToString();
databaseValue = await TimerProcessGetValue();
await InvokeAsync(StateHasChanged);
}, null, 0, 1000);
}
catch
{
// empty on purpose
}

最佳答案

https://learn.microsoft.com/en-us/dotnet/api/system.threading.timer?view=net-5.0

When a timer is no longer needed, use the Dispose method to free the resources held by the timer. Note that callbacks can occur after the Dispose() method overload has been called, because the timer queues callbacks for execution by thread pool threads. You can use the Dispose(WaitHandle) method overload to wait until all callbacks have completed.

这就是为什么在处理组件后调用 await InvokeAsync(StateHasChanged); 的原因。

关于c# - 更新页面时 Blazor Server System.ObjectDisposedException 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69458873/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com