Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 组合ConcurrentQueue和ConcurrentStack_C#_.net_Multithreading_Collections - Fatal编程技术网

C# 组合ConcurrentQueue和ConcurrentStack

C# 组合ConcurrentQueue和ConcurrentStack,c#,.net,multithreading,collections,C#,.net,Multithreading,Collections,我正在寻找一个同时收集,可以从双方访问。我希望实现以下目标: 一些制作人添加了一些项目 客户应能够显示最近生产的n个项目 该集合应仅包含最近x小时内产生的元素 因此,我需要访问列表的顶部(FIFO)来显示最后n个项目,但我还需要访问列表的末尾(LIFO)来连续删除超过x小时的元素 客户应能够显示最近生产的n个项目 这与删除项目无关。我想你想让他们在展示完后留在那里。 所以你并不真的想要后进先出的部分 当项目数量不太大时,可以使用ConcurrentQueue和ToArray()获取快照(并且

我正在寻找一个同时收集,可以从双方访问。我希望实现以下目标:

  • 一些制作人添加了一些项目
  • 客户应能够显示最近生产的n个项目
  • 该集合应仅包含最近x小时内产生的元素
因此,我需要访问列表的顶部(FIFO)来显示最后n个项目,但我还需要访问列表的末尾(LIFO)来连续删除超过x小时的元素

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

这与删除项目无关。我想你想让他们在展示完后留在那里。 所以你并不真的想要后进先出的部分


当项目数量不太大时,可以使用ConcurrentQueue和ToArray()获取快照(并且只使用前n个项目)

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

我创建了一个类来保存保存的值和时间戳

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

    public T Value { get; set; }
}
公共类SavedItem
{
公共日期时间时间戳{get;set;}
公共T值{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);
    }
}
公共类过期集合
{
私有只读存储器缓存;
私有只读时间限制;
公共过期集合(整数小时限制)
{
_缓存=新的内存缓存(“样本”);
_小时限制=小时限制;
}
公共无效添加(T值)
{
var item=CreateCacheItem(值);
var policy=CreateItemPolicy();
_cache.Add(项、策略);
}
private CacheItem CreateCacheItem(T值)
{
var addedValue=新的SavedItem
{
时间戳=日期时间。现在,
价值=价值
};
//创建唯一密钥以满足MemoryCache契约
var uniqueKey=Guid.NewGuid().ToString();
返回新的缓存项(uniqueKey,addedValue);
}
私有CacheItemPolicy CreateItemPolicy()
{
//这将设置从缓存中删除项的时间
var expirationTime=DateTime.Now.AddHours(\u hoursLimit);
var offset=新的DateTimeOffset(expirationTime);
返回新的CacheItemPolicy
{
绝对过期=偏移量
};
}
公共IEnumerable GetLast(整数金额)
{
返回_cache.Select(pair=>(SavedItem)pair.Value)
.OrderBy(项=>item.Timestamp)
.Select(项=>item.Value)
.收取(金额);
}
}

为什么不能同时使用两者?使用
Add
方法将它们包装到一个类中,该方法会将给定项添加到both@Fabio:您将必须使用某种锁定机制同步对两个单独集合的访问,但是您也可以使用由锁保护的单个列表,这应该是问题的解决方案。但是,这个问题特别提到了一个并发集合。堆栈将被填满,无法删除旧项。FIFO数据结构总是在开始时有其最早的项。因此,队列中的第一项是最早的,而不是最后一项。要删除超过某个时间跨度的项目,您必须在显示前验证每个已出列的项目,或定期从头到尾删除项目范围。您是否查看过BlockingCollection,它允许生产商发出生产结束的信号@ManuelFaux,您可以使用
MemoryCache
删除“到期”项。为了提高性能,我将使用“SkipWhile()”,因为“Where()”会在整个集合中迭代以比较每个项。“ConcurrentBag”是无序的。这需要搜索整个包,通过比较每个包的日期时间来查找最后添加的项目。如果你想使用一个列表或数组,你只需要从末尾获取最新的。现在,您可以使用SkipWhile()在集合中线性移动。和Take()或TakeWhile()不修改源集合。您必须自己删除这些项目,否则备份集将包含过时的数据,并且增长缓慢down@BionicCode,使用另一种方法更新了答案,该方法应处理删除“过期”值的问题。