结合ConcurrentQueue和ConcurrentStack

时间:2018-05-01 08:13:34

标签: c# .net multithreading collections

我正在寻找可以从双方访问的并发集合。我想实现以下目标:

  • 一些制作人添加项目
  • 客户端应能够显示最后 n 生成的项目
  • 该集合仅包含在最后 x 小时内生成的元素

所以我需要访问列表顶部(FIFO)以显示最后的 n 项,但我还需要访问列表末尾(LIFO)来修剪早于<的元素em> x 小时。

2 个答案:

答案 0 :(得分:3)

另一种方法是使用MemoryCache类,它是线程安全的,并提供用于删除“过期”项的内置功能。<​​/ p>

我创建了一个用于保存已保存值和时间戳的类

public class SavedItem<T>
{
    public DateTime Timestamp { get; set; }

    public T Value { get; set; }
}

Collection类将有两个方法:一个用于添加,另一个用于检索N个最后一个项

public class ExpiredCollection
{
    private readonly MemoryCache _cache;

    private readonly int _hoursLimit;

    public ExpiredCollection(int hoursLimit)
    {
        _cache = new MemoryCache("sample");
        _hoursLimit = hoursLimit;
    }

    public void Add<T>(T value)
    {
        var item = CreateCacheItem(value);
        var policy = CreateItemPolicy();

        _cache.Add(item, policy);
    }

    private CacheItem CreateCacheItem<T>(T value)
    {
        var addedValue = new SavedItem<T>
        {
            Timestamp = DateTime.Now,
            Value = value
        };
        // Create unique key to satisfy MemoryCache contract
        var uniqueKey = Guid.NewGuid().ToString();

        return new CacheItem(uniqueKey, addedValue);
    }

    private CacheItemPolicy CreateItemPolicy()
    {
        // This will set a time when item will be removed from the cache
        var expirationTime = DateTime.Now.AddHours(_hoursLimit);
        var offset = new DateTimeOffset(expirationTime);

        return new CacheItemPolicy
        {
            AbsoluteExpiration = offset
        };
    }

    public IEnumerable<T> GetLast<T>(int amount)
    {
        return _cache.Select(pair => (SavedItem<T>)pair.Value)
                     .OrderBy(item => item.Timestamp)
                     .Select(item => item.Value)
                     .Take(amount);
    }
}

答案 1 :(得分:2)

  

客户端应能够显示最后n个产生的项目

这不是关于删除项目。我假设你希望他们在展示后留在那里。 所以你真的不想要LIFO部分。

如果项目数量太大,您可以使用ConcurrentQueue和ToArray()来获取快照(并且仅使用前n个项目)。