【问题标题】:ASP.NET: cache task and call its result in synchronous codeASP.NET:缓存任务并以同步代码调用其结果
【发布时间】:2017-03-12 17:10:21
【问题描述】:

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

【问题讨论】:

  • 有什么具体问题吗?

标签: asp.net caching async-await task


【解决方案1】:

没关系。

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

在您的fallback here; I can use data from some synchronous source 处理中,您还可以阻止任务(或在架构上可能的情况下等待它)。

HTTP 处理程序也支持使用任务的异步处理。我相信您需要一个易于编写或在网络上可用的小型助手/包装器。

【讨论】:

  • 是的,我知道它需要进程内模式。
  • 关于回退:在实际项目中我有同步调用那里的数据库。
  • 我知道我可以使用异步 httphandlers,但是项目很大,在很多地方引入异步工作流非常困难。
  • 我正在考虑从多个请求中访问这个静态类。 HttpRuntime.Cache 是线程安全的,所以检查 null 和其他工作是否正常(我想)。但是:如果我想在静态变量中缓存数据而不是缓存,则需要为“if (Cache[CacheKey] == null) {...}”添加锁,对吗?
  • 您在这里只使用线程安全缓存,因此无需担心。使用静态变量,您确实需要同步。 ConcurrentDict&lt;TKey, Lazy&lt;TValue&gt;&gt; 是一种简单且安全的解决方案,但它不支持驱逐。
猜你喜欢
  • 2023-03-27
  • 2020-12-20
  • 2021-09-09
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
相关资源
最近更新 更多