C# - 如何将 GetFromJsonAsync 的结果分配给变量,并在不重复调用 GET 请求的情况下使用它?

C# - How to assign the result of GetFromJsonAsync to a variable, and use it without it repeatedly calling the GET request?

我正在尝试将 GET 请求的结果分配给 class 属性,这样 class 中的所有其他方法都可以使用 [=18] 的值=] 而不必多次调用 GET 请求。底线是我想在 class 实例化期间调用 GET 请求,将其分配给一个变量,然后在对象生命周期内不再调用它。

public class Example {
  
  private readonly HttpClient _http;
  private readonly List<Thing> _things;
  
  public Example(HttpClient http) 
  {
    _http = http;
    _things = _http.GetFromJsonAsync<List<Thing>>("https://api-to-call/endpoint").Result;
  }

  public void UseThings()
  {
    // Do something with _things;
  }

}

但是,当调用该方法时,它会发送一个新的 GET 请求以检索我在构造函数中分配的 属性 的更新值。我如何编写代码,使其在对象实例化期间仅调用一次 GET 请求?

您不应在构造函数中阻塞,并且 .Result 可能会产生严重的副作用。虽然已经讨论了支持此功能的语言功能,但在那之前,您应该将其移出缓存操作。您可以通过使用 SemaphoreSlim.

包装 http 调用来确保该操作只运行一次
public class Example
{
    private readonly HttpClient _http;
    private static readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
    private List<Thing> _things;

    public Example(HttpClient http)
    {
        _http = http;
    }

    public async Task UseThings()
    {
        // Do something with _things;
        var localThings = _things ?? await GetThingsAsync();
    }
    
    private async Task<List<Thing>> GetThingsAsync()
    {
        if (_things != null)
        {
            return await Task.FromResult(_things);
        }
        
        await _lock.WaitAsync();
        try
        {
            // double check in case another thread has completed
            if (_things != null)
            {
                return _things;
            }
            
            _things = await _http.GetFromJsonAsync<List<Thing>>("https://api-to-call/endpoint");
            return _things;
        }
        finally 
        {
            _lock.Release();
        }   
    }
}