【发布时间】:2020-03-02 10:00:16
【问题描述】:
出于演示目的,假设我有一个名为 StateManager 的类:
public class StateManager
{
public StateManager()
{
IsRunning = false;
}
public void Initialize()
{
Id = Guid.NewGuid().ToString();
IsRunning = true;
KeepSession();
}
public void Dispose()
{
Id = null;
IsRunning = false;
}
public string Id { get; private set; }
public bool IsRunning { get; private set; }
private async void KeepSession()
{
while(IsRunning)
{
Console.WriteLine($"{Id} checking in...");
await Task.Delay(5000);
}
}
}
它有一个在启动后运行的方法,每 5 秒将它的 Id 写入控制台。
在我的 Startup 类中,我将其添加为 Scoped 服务:
services.AddScoped<StateManager>();
也许我使用了错误的位置,但在我的 MainLayout.razor 文件中,我在 OnInitializedAsync()
上对其进行了初始化@inject Models.StateManager StateManager
...
@code{
protected override async Task OnInitializedAsync()
{
StateManager.Initialize();
}
}
在呈现第一页后运行应用程序时,控制台输出显示有 2 个实例正在运行:
bcf76a96-e343-4186-bda8-f7622f18fb27 正在登记...
e5c9824b-8c93-45e7-a5c3-6498b19ed647 正在登记...
如果我在对象上运行 Dispose() 它会结束其中一个实例上的 KeepSession() while 循环,但另一个实例继续运行。如果我运行 Initialize() 会出现一个新实例,并且每次运行 Initialize() 都会生成新实例,并且它们都使用其唯一 ID 写入控制台。我可以无限制地创建任意数量。
我认为将 Scoped 服务注入 DI 可以保证每个电路都有一个该对象的单个实例?我还尝试在 OnAfterRender() 覆盖中进行初始化,以防预渲染过程创建双重实例(尽管这不能解释为什么我可以在注入服务的页面中创建这么多实例)。
有什么我没有正确处理的吗?除了 MainLayout,还有更好的初始化 StateManager 的位置吗?
【问题讨论】:
标签: c# .net asp.net-core blazor blazor-server-side