我在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方法(总是这样做,这次忘记了(