我正在寻找一种优雅的方式来缓存我的异步操作的结果。缓存异步操作
我第一次碰到这样的同步方法:
public String GetStuff(String url)
{
WebRequest request = WebRequest.Create(url);
using (var response = request.GetResponse())
using (var sr = new StreamReader(response.GetResponseStream()))
return sr.ReadToEnd();
}
然后我做了异步:
public async Task<String> GetStuffAsync(String url)
{
WebRequest request = WebRequest.Create(url);
using (var response = await request.GetResponseAsync())
using (var sr = new StreamReader(response.GetResponseStream()))
return await sr.ReadToEndAsync();
}
于是我决定,我应该缓存的结果,所以我并不需要查询外面那往往:
ConcurrentDictionary<String, String> _cache = new ConcurrentDictionary<String, String>();
public async Task<String> GetStuffAsync(String url)
{
return _cache.GetOrAdd(url, await GetStuffInternalAsync(url));
}
private async Task<String> GetStuffInternalAsync(String url)
{
WebRequest request = WebRequest.Create(url);
using (var response = await request.GetResponseAsync())
using (var sr = new StreamReader(response.GetResponseStream()))
return await sr.ReadToEndAsync();
}
然后,我读了一篇文章(o看了一个视频)关于如何cachi NG Task<T>
是更好的,因为他们创造昂贵:
ConcurrentDictionary<String, Task<String>> _cache = new ConcurrentDictionary<String, Task<String>>();
public Task<String> GetStuffAsync(String url)
{
return _cache.GetOrAdd(url, GetStuffInternalAsync(url));
}
private async Task<String> GetStuffInternalAsync(String url)
{
WebRequest request = WebRequest.Create(url);
using (var response = await request.GetResponseAsync())
using (var sr = new StreamReader(response.GetResponseStream()))
return await sr.ReadToEndAsync();
}
而现在的问题是,如果请求失败(例如:一个HTTP 401),高速缓存将包含一个失败Task<String>
,我将不得不重新设置该应用程序,因为它将不可能重新发送请求。
是否有一种优雅的方式使用ConcurrentDictionary<T1,T2>
缓存只成功的任务,仍然有原子行为?
操作系统已经为您缓存了HTTP请求,并且会正确地遵循HTTP语义(即不缓存401)。 –
https://stackoverflow.com/questions/31831860/async-threadsafe-get-from-memorycache –