如何在Blazor应用程序中防止计时器泄漏



我在stackoverflow C#计数器中发布了一个问题的答案,以计数到目标数字。答案是:

你可以创建一个定时器服务,可以在很多场合为你服务:

创建服务类:

public class BlazorTimer
{
private Timer _timer;
internal void SetTimer(double interval)
{
_timer = new Timer(interval);
_timer.Elapsed += NotifyTimerElapsed;
_timer.Enabled = true;
_timer.Start();
}
private void NotifyTimerElapsed(object sender, ElapsedEventArgs e)
{
OnElapsed?.Invoke();
}
public event Action OnElapsed;
}

将服务添加到程序中的DI容器中。主方法,作为瞬态:

builder.Services.AddTransient(config =>
{
var blazorTimer = new BlazorTimer();
blazorTimer.SetTimer(1000);
return blazorTimer;
});

用法

@page "/"
@implements IDisposable
@inject BlazorTimer Timer
@count.ToString()

@code{
private int count = 0;
protected override void OnInitialized()
{
Timer.OnElapsed += NotifyTimerElapsed;
base.OnInitialized();
}
private void NotifyTimerElapsed()
{
// Note: WebAssembly Apps are currently supporting a single thread, which 
// is why you don't have to call
// the StateHasChanged method from within the InvokeAsync method. But it 
// is a good practice to do so in consideration of future changes, such as 
// ability to run WebAssembly Apps in more than one thread.
InvokeAsync(() => { count++; StateHasChanged(); });
}
public void Dispose()
{
Timer.OnElapsed -= NotifyTimerElapsed;
}
}

然而,我被告知

BlazorTimer正在泄漏timer。计时器是IDisposable

取消订阅Blazor组件中实现的Dispose方法中的事件处理程序是否会导致BlazorTimer泄漏计时器(_T(。事实上,我并不完全理解";BlazorTimer正在泄漏timer。定时器是IDisposable",因此,让我问一下,如何防止计时器泄漏,同时使用代码取消订阅Blazor组件中实现的Dispose方法中的事件处理程序?除了跳过事件处理程序的取消订阅之外,还有什么方法可以防止这种泄漏吗。

BlazorTimer应该实现IDisposable。BlazorTimerDispose方法应停止计时器,取消订阅Elapsed事件,然后处置计时器。

问题的根源是您的BlazorTimer被设置为瞬态服务。因此,对于每个新的请求,您都会得到新的BlazorTimer对象和新的.Net计时器,这些计时器永远不会被正确地处理

好的,多亏了mkArtakMSFT和Peter Morris,我已经解决了这个问题。

一般经验法则是,每次封装一次性类型在新类型中作为成员,您应该类型也是一次性的。在您的特定情况下,BlazorTimer类是不是一次性的-因此是底层timer实例,当初始化,永远不会被处理-留下一些内存。

此外,每次调用SetTimer方法时,都会有一个新的Timer正在创建实例,而旧实例将被遗留在后面(in空气(,再次泄漏存储器。考虑处置现有例如,如果这是你的意图。或者,更好的是,重用现有的例如,如果您的业务规则可以接受源

注意:"BlazorTimer类不是一次性的";因为我使用的是瞬态依赖关系。将其作为一次性使用会产生不利影响。。。参见blazor大学的解释

为了解决内存泄漏的问题,在我当前的代码片段中,我应该简单地从NotifyTimerFailed方法对Timer对象调用Dispose方法(总是这样做,这次忘记了(

相关内容

  • 没有找到相关文章