在字典中缓存async http结果

时间:2018-03-14 00:12:08

标签: c# asynchronous caching async-await .net-core

我想知道检索以前缓存的对象的最佳方法是什么。

下面的代码可以工作,但是从字典中获取对象的位看起来可以做得更好。我觉得我可能会遗漏一些重要的事情。

public class ResourceProvider
{
    private readonly IDictionary<string, string> _cachedResources;

    public async Task<string> GetResource(string url)
    {
        // If there is a cached version use that
        if (_cachedResources.ContainsKey(url))
        {
            // I am not sure this is the proper way if doing it
            return await Task.Factory.StartNew(() => _cachedResources[url]);
        }

        // Get resource (i know httpclient is better as a static)
        var resource = await new HttpClient().GetStringAsync(url);

        _cachedResources.Add(url, resource);

        return resource;
    }
}

2 个答案:

答案 0 :(得分:1)

一般情况下,我建议您使用IMemoryCache界面。因为您可以轻松地在内存缓存或redis缓存服务器(天蓝色)之间切换。这比家庭酿造解决方案更具优势。

用法非常简单。您只需按键缓存对象。密钥必须是唯一的,就像您在样本中所做的那样。您可以配置绝对或相对 到期,优先级和滑动到期,以便您可以根据需要进行操作。 它比简单的hashmap要好得多。

在本文中,How to use caching解释了如何将everthing设置为起点。

答案 1 :(得分:0)

可以根据需要多次等待任务。你可以这样做:

public class ResourceProvider
{
    private readonly ConcurrentDictionary<string, Task<string>> cachedResources
        = new ConcurrentDictionary<string, ValueTask<string>>();

    public Task<string> GetResource(string url)
        => this.cachedResources.GetOrAdd(url, u => new new HttpClient().GetStringAsync(u));
}

由于您需要在大多数时间从缓存中获取值,现在有一个值任务(ValueTask<TResult> Struct):

public class ResourceProvider
{
    private readonly ConcurrentDictionary<string, ValueTask<string>> cachedResources
        = new ConcurrentDictionary<string, ValueTask<string>>();

    public ValueTask<string> GetResource(string url)
        => this.cachedResources.GetOrAdd(
            url,
            u => new ValueTask<string>(new HttpClient().GetStringAsync(u)));
}