单例服务上的ASP.NET核心调用异步初始化

时间:2019-05-10 12:02:26

标签: c# asp.net-core dependency-injection

我有一项服务,该服务通过称为InitAsync

的方法从文件中异步读取某些内容。
public class MyService : IService {
    private readonly IDependency injectedDependency;

    public MyService(IDependency injectedDependency) {
        this.injectedDependency = injectedDependency;
    }

    public async Task InitAsync() {
        // async loading from file.
    }
}

现在此服务已注入我的控制器中。

public class MyController : Controller {
    private readonly IService service;

    public MyController(IService service) {
        this.service = service;
    }
}

现在,我需要MyService的单例实例。我想在启动时调用InitAsync。

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        ......
        services.AddSingleton<IService, MyService>();
        var serviceProvider = services.BuildServiceProvider();
        // perform async init.
        serviceProvider.GetRequiredService<IService>().InitAsync();
    }
}

正在发生的事情是在启动时,创建了MyService的实例,并在其上调用了InitAsync()。然后,当我调用控制器类时,将创建另一个MyService实例,然后将其重新用于后续调用。

我需要的是仅在启动时初始化一个实例,称为InitAsync(),并让它也可以被控制器重用。

1 个答案:

答案 0 :(得分:2)

  

正在发生的事情是在启动时,创建了MyService的实例,并在其上调用了InitAsync()。然后,当我调用控制器类时,将创建另一个MyService实例,然后将其重新用于后续调用。

调用BuildServiceProvider()时,将创建一个IServiceProvider的单独实例,该实例将创建自己的IService的单例实例。解决为IServiceProvider提供的IService时使用的MyController与您自己创建的IService不同,因此IService本身也不同(并且未初始化)。

  

我需要的是仅在启动时初始化一个实例,称为InitAsync(),并让它也可以被控制器重用。

您可以尝试在Startup.ConfigureServices内解析和初始化Program.Main内的IService。这有两件事:

  1. 使用await same 实例进行初始化和以后使用。
  2. InitAsync拨打Program.Main的电话,该电话目前已在您所展示的方法中被抛弃。

以下是public static async Task Main(string[] args) { var webHost = CreateWebHostBuilder(args).Build(); await webHost.Services.GetRequiredService<IService>().InitAsync(); webHost.Run(); // await webHost.RunAsync(); } 的外观示例:

await

这使用async Main启用IWebHost,构建IServiceProvider并使用其IService来解析和初始化await。该代码还显示了如何使用RunAsyncasync来使用specialization,现在方法是use std::hash::{Hash,Hasher}; #[derive(Debug, Copy, Clone,PartialEq,Eq)] struct HashKey<T>(T); //default impl<T : Hash> Hash for HashKey<T> { fn hash<H>(&self, state: &mut H) where H : Hasher { self.0.hash(state) } } impl Hash for HashKey<f32> { fn hash<H>(&self, state: &mut H) where H : Hasher { unsafe { std::mem::transmute::<f32,u32>(self.0) }.hash(state) } } impl Hash for HashKey<f64> { fn hash<H>(&self, state: &mut H) where H : Hasher { unsafe { std::mem::transmute::<f64,u64>(self.0) }.hash(state) } }