自定义队列机制和锁

时间:2018-03-26 08:36:45

标签: c# multithreading

我想知道将自定义队列机制更改为BlockingCollection和Concurency集合是否更好。我应该删除任何锁吗? 我想做一些类似于制作人consomer模式的东西。 我有一个生产者和多个消费者。也许,我应该使用BlockingCollection而不是CustomQueue和ConcurrentDictionary而不是processedBuffer,Buffer dictionaries吗?我必须使用.Net 4.0 versoin。

 public interface IId
    {
        Guid Id { get; }
    }

    public class CustomQueue:Queue
    {
        private List<object> queueMirror;

        public CustomQueue()
        {
            queueMirror = new List<object>();
        }

        public override void Enqueue(object obj)
        {
            lock (SyncRoot)
            {
                base.Enqueue(obj);
                queueMirror.Add(((IId)obj).Id);
            }
        }

        public override object Dequeue()
        {
            lock (SyncRoot)
            {
                object obj = base.Dequeue();
                queueMirror.Remove((obj as IId).Id);
                return obj;
            }
        }

        public override bool Contains(object obj)
        {
            lock (SyncRoot)
            {
                if ((obj as IId) != null)
                {
                    return queueMirror.Contains(((IId)obj).Id);
                }
                return queueMirror.Contains(obj);
            }
        }
    }


public class MyCustomQueue
{
    private bool isReady;

    private readonly object syncObj;

    private const int capacity = 10000;
    private const int duration = 10000;
    private const int min_size = 30;
    private const int clean_duration = 50000; 

    private readonly Timer fetchTimer;
    private readonly Timer clearTimer;

    private readonly CustomQueue customQueue;

    private readonly Dictionary<Guid, DateTime> Buffer;

    private readonly Dictionary<Guid, DateTime> processedBuffer;

    public int Count
    {
        get
        {
            lock (syncObj)
            {
                return customQueue.Count;
            }
        }
    }

    public int BufferCount
    {
        get
        {
            lock (syncObj)
            {
                return Buffer.Count;
            }
        }
    }

    public void Start()
    {
        fetchTimer.Enabled = true;
        fetchTimer.Start();
        clearTimer.Enabled = true;
        clearTimer.Start();
    }

    public void Stop()
    {
        fetchTimer.Enabled = false;
        fetchTimer.Stop();
        clearTimer.Enabled = false;
        clearTimer.Stop();
    }


    public MyCustomQueue()
    {
        buffer = new Dictionary<Guid, DateTime>();
        processedBuffer = new Dictionary<Guid, DateTime>();
        customQueue = new CustomQueue();
        syncObj = new object();
        isReady = true;

        clearTimer = new Timer(QBUFFER_CLEAR_DURATION) { Interval = clean_duration };
        clearTimer.Elapsed += ClearTimerElapsed;

        fetchTimer = new Timer(duration) { Interval = duration };
        fetchTimer.Elapsed += FetchTimerElapsed;
    }

    private void FetchTimerElapsed(object sender, ElapsedEventArgs e)
    {
        if (isReady)
        {
            if (Count < min_size)
            {
                Process();
            }
        }
    }

    private void ClearTimerElapsed(object sender, ElapsedEventArgs e)
    {
        var itemsToRemove = new List<Guid>();
        lock (syncObj)
        {
            DateTime currentTime = DateTime.Now;

            foreach (KeyValuePair<Guid, DateTime> processedDocKvp in processedBuffer)
            {
                Guid processedId = processedDocKvp.Key;
                DateTime processedDataTime = processedBuffer[processedId];

                if (processedDataTime != null && (currentTime - processedDataTime).TotalMilliseconds > clean_duration)
                {
                    Buffer.Remove(processedId);
                    itemsToRemove.Add(processedId);
                }
            }
            foreach (Guid messageId in itemsToRemove)
            {
                if (processedBuffer.ContainsKey(messageId))
                    processedBuffer.Remove(messageId);
            }
        }
    }

    private void Process()
    {
        isReady = false;

            try
            {
                List<IItem> items = Engine.GetDocumentFromEngine();
                AddToQueue(items);
            }
            catch (Exception exception)
            {
               ...
            }

        isReady = true;
    }

    private void AddToQueue(List<IItem> items)
    {
        if (items != null)
        {
            if (items.Count != 0)
            {
                foreach (IItem item in items)
                {
                    EnqueueItem(item);
                }
            }
        }
    }

    private void EnqueueItem(IItem item)
    {
        Guid Id = item.Id;

        lock (syncObj)
        {
            if (!Buffer.ContainsKey(Id))
            {
                DateTime dataTime = DateTime.Now;
                Buffer.Add(Id, dataTime);
                customQueue.Enqueue(item);
            }
            return null;
        }
    }

    public IItem DequeueItem()
    {
        lock (syncObj)
        {
            if (customQueue.Count == 0)
            {
                return null;
            }
            var item = (IItem)customQueue.Dequeue();
            return item;
        }
    }

    public void RemoveItem(IId item)
    {
        Guid Id = item.Id;
        lock (syncObj)
        {
            if (!processedBuffer.ContainsKey(Id))
            {
                DateTime dataTime = DateTime.Now;
                processedBuffer.Add(Id, dataTime);
            }

        }
    }
}

0 个答案:

没有答案