【问题标题】:How to add data from async method in singleton in Startup.cs in net.core 3.0?如何在 net.core 3.0 的 Startup.cs 中从单例中的异步方法添加数据?
【发布时间】:2020-11-11 23:05:13
【问题描述】:

我正在尝试从 HttpClient 获取异步数据,并将此数据作为单例添加到 Startup.cs 中的 ConfigureServices

public static class SolDataFill
{
    static HttpClient Client;

    static SolDataFill()
    {
        Client = new HttpClient();
    }

    public static async Task<SolData> GetData(AppSettings option)
    {
        var ulr = string.Format(option.MarsWheaterURL, option.DemoKey);
        var httpResponse = await Client.GetAsync(ulr);

        var stringResponse = await httpResponse.Content.ReadAsStringAsync();

        var wheather = JsonConvert.DeserializeObject<SolData>(stringResponse);
        return wheather;
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(Configuration);
    var settings = Configuration.GetSection("NasaHttp") as AppSettings;
    var sData = await SolDataFill.GetData(settings);
    services.AddSingleton<SolData>(sData);
}

有一个错误:可以仅将 await 与 async 一起使用。如何将数据从异步方法添加到单例?

【问题讨论】:

  • 你试过var sData = SolDataFill.GetData(settings).Result;吗?
  • 你可以使用GetAwaiter().GetResult()同步运行这个方法

标签: c# .net-core asp.net-core-3.0


【解决方案1】:

也许您应该考虑重新设计您的 SolDataFill 以最终成为 DataService,而不是将所有内容都添加到 DI 容器中。

然后每个需要数据的人都可以查询它。 (这就是为什么我在这里添加缓存以不总是做请求)

public class SolDataFill
{
    private readonly HttpClient _client;
    private readonly AppSettings _appSettings;
    private readonly ILogger _logger;
    
    private static SolData cache;
    
    public SolDataFill(HttpClient client, AppSettings options, ILogger<SolDataFill> logger)
    {
        _client = client;
        _appSettings = options;
        _logger = logger;
    }

    public async Task<SolData> GetDataAsync()
    {
        if(cache == null)
        {
            var ulr = string.Format(_appSettings.MarsWheaterURL, _appSettings.DemoKey);
            _logger.LogInformation(ulr);
            var httpResponse = await _client.GetAsync(ulr);
            if(httpResponse.IsSuccessStatusCode)
            {
                _logger.LogInformation("{0}", httpResponse.StatusCode);
                var stringResponse = await httpResponse.Content.ReadAsStringAsync();
                cache = JsonConvert.DeserializeObject<SolData>(stringResponse);
                return cache;
            }
            else
            {
                _logger.LogInformation("{0}", httpResponse.StatusCode);
            }
        }
        return cache;
    }
}

Full example can be found here

就像在您的问题的 cmets 中所写的那样,通过 GetAwaiter().GetResult() 同步运行异步方法非常简单。但在我看来,每次看到这段代码时,我个人认为隐藏了一种可以重构的代码气味。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多