【问题标题】:C# How to make a ConcurrentQueue to be cleaned by the conditionC# 如何使 ConcurrentQueue 被条件清除
【发布时间】:2016-07-25 14:20:59
【问题描述】:

如何使 ConcurrentQueue 被第一个元素的条件清除。例如清除较旧的博客文章。我想出了一个 ConditionConcurrentQueue 的想法:

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading;

public class ConditionConcurrentQueue<T> : ConcurrentQueue<T>
    where T: class
{
    public ConditionConcurrentQueue(Func<T, bool> condition)
        : this(null, condition)
    { }

    public ConditionConcurrentQueue(IEnumerable<T> items, Func<T, bool> condition)
        : base(items)
    {
        _condition = condition;
    }

    private Func<T, bool> _condition;

    public virtual void Enqueue(T item)
    {
        T removed;
        bool cleaningRun = true;
        int failedCnt = 0;

        while (!IsEmpty && cleaningRun && failedCnt < 10)
        {
            if (TryPeek(out removed))
            {
                bool result = _condition.Invoke(removed);

                if (!result)
                {
                    if (!TryDequeue(out removed))
                    {
                        failedCnt++;
                        Thread.Sleep(10);
                    }
                }
                else
                    cleaningRun = false;
            }
            else
            {
                failedCnt++;
                Thread.Sleep(10);
            }
        }

        base.Enqueue(item);
    }
}

使用这个ConditionConcurrentQueue可以是这样的:

class Blog
{
    public ConditionConcurrentQueue<Post> Posts { get; set; }
}

class Post
{
    public DateTime Time { get; set; }

    public string Text { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Blog blog = new Blog
        {
            Posts = new ConditionConcurrentQueue<Post>(
            new Post[] { 
                         new Post { Time = DateTime.Now - TimeSpan.FromMinutes(80), Text = "Title 1" },
                         new Post { Time = DateTime.Now - TimeSpan.FromMinutes(60), Text = "Title 2" },
                         new Post { Time = DateTime.Now - TimeSpan.FromMinutes(40), Text = "Title 3" },
                       },
            p => p.Time > DateTime.Now - TimeSpan.FromHours(1))
        };

        blog.Posts.Enqueue(new Post { Time = DateTime.Now - TimeSpan.FromMinutes(20), Text = "Title 4" });

        foreach (Post post in blog.Posts.ToList())
            Console.WriteLine(post.Text);
    }
}

也许这是太原始的解决方案。 我将不胜感激任何改进。谢谢。

【问题讨论】:

    标签: linq c#-4.0 concurrent-queue


    【解决方案1】:

    从 .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0 开始,ConcurrentQueue&lt;T&gt; 上有一个 Clear() 方法。请参阅:ConcurrentQueue.Clear

    【讨论】:

      【解决方案2】:

      另外,您可以通过扩展方法尝试:

          public static ICollection<T> Enqueue<T>(this ConcurrentQueue<T> field, T item, Func<T, bool> predicate)
          {
              ICollection<T> removed = field.TryDequeue<T>(predicate);
      
              field.Enqueue(item);
      
              return removed;
          }
      
          public static ICollection<T> TryDequeue<T>(this ConcurrentQueue<T> field, Func<T, bool> predicate)
          {
              T comparedItem;
              var removedList = new List<T>();
      
              while (field.TryPeek(out comparedItem))
              {
                  if (!predicate.Invoke(comparedItem))
                  {
                      if (field.TryDequeue(out comparedItem))
                          removedList.Add(comparedItem);
                      else
                          break;
                  }
                  else
                      break;
              }
      
              return removedList;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        • 2016-10-11
        • 2014-03-14
        • 2010-09-14
        相关资源
        最近更新 更多