我有同步 HttpHandler 。我想缓存 HttpClient.GetAsync 的结果,并在我的 HttpHandler 中使用它。我是这样做的:
public static class CacheFacade
{
private static Cache Cache => HttpRuntime.Cache;
private const string CacheKey = "asynccache";
private static readonly object _lockObject = new object();
public static string GetStringFromCache()
{
if (Cache[CacheKey] == null)
{
lock(_lockObject)
{
if (Cache[CacheKey] == null)
{
InitCache();
}
}
//fallback here; I can use data from some synchronous source
return "init cache" + " - " + Thread.CurrentThread.ManagedThreadId;
}
var task = (Task<string>) Cache[CacheKey];
if (!task.IsCompleted)
{
//and fallback here too
return task.Status + " - " + DateTime.UtcNow + " - " + Thread.CurrentThread.ManagedThreadId;
}
return task.Result;
}
private static void InitCache()
{
var task = Task.Run(GetDataAsync);
Cache.Insert(CacheKey, task, null, DateTime.Now.Add(TimeSpan.FromSeconds(10)),
Cache.NoSlidingExpiration);
}
private static async Task<string> GetDataAsync()
{
using (var httpClient = new HttpClient())
{
await Task.Delay(TimeSpan.FromSeconds(2));
var res = await httpClient.GetAsync("http://www.google.com");
return res.StatusCode + " - " + DateTime.UtcNow + " - " + Thread.CurrentThread.ManagedThreadId;
}
}
}
有效。这种方法有什么缺点吗? 更新:根据https://en.wikipedia.org/wiki/Double-checked_locking添加双重检查锁定。
答案 0 :(得分:1)
没关系。
请注意,这些缓存项目只能存储在进程中。您无法使用进程外缓存,因为无法序列化任务。您可能会或可能不会关心这一点。
在你的fallback here; I can use data from some synchronous source
处理中,你也可以阻止任务(或者在架构上可以等待它)。
HTTP处理程序也支持使用任务进行异步处理。我相信你需要一个小帮手/包装器,它易于编写或在网上提供。