2016-04-05 2 views
0

Wie man eine ConcurrentQueue bereinigt, die von der Bedingung für die ersten Elemente bereinigt wird. ZB um ältere Blogposts zu löschen. Ich kam mit dieser Idee einer ConditionConcurrentQueue up:C# Wie man eine ConcurrentQueue so macht, dass sie durch die Bedingung bereinigt wird

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); 
    } 
} 

verwenden ConditionConcurrentQueue könnte so:

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); 
    } 
} 

vielleicht ist es zu primitiv Lösung. Ich würde alle Verbesserungen schätzen. Vielen Dank.

Antwort

0

auch, können Sie durch die Erweiterung Methode versuchen:

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; 
    } 
Verwandte Themen