首页 > 解决方案 > 如何在 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 容器中,在 Program.Main 方法中,作为瞬态:

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 泄漏 _timer。实际上我并不完全理解“BlazorTimer 正在泄漏 _timer。Timer 是 IDisposable”,所以让我问一下,我怎样才能防止计时器泄漏,但在实现的 Dispose 方法中使用代码取消订阅事件处理程序Blazor 组件?除了跳过事件处理程序的取消订阅之外,还有什么方法可以防止这种泄漏。

标签: blazorblazor-webassembly

解决方案


BlazorTimer 应该实现 IDisposable。BlazorTimer Dispose 方法应停止计时器、取消订阅 Elapsed 事件并释放计时器。

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


推荐阅读