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();
}
}
}
我正在尝试将 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
.
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();
}
}
}