ASP.NET:缓存任务并在同步代码中调用其结果

时间:2016-10-30 10:48:58

标签: asp.net caching async-await task

我有同步 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添加双重检查锁定。

1 个答案:

答案 0 :(得分:1)

没关系。

请注意,这些缓存项目只能存储在进程中。您无法使用进程外缓存,因为无法序列化任务。您可能会或可能不会关心这一点。

在你的fallback here; I can use data from some synchronous source处理中,你也可以阻止任务(或者在架构上可以等待它)。

HTTP处理程序也支持使用任务进行异步处理。我相信你需要一个小帮手/包装器,它易于编写或在网上提供。