What type of IProducerConsumerCollection to use for my task?

后端 未结 2 741
礼貌的吻别
礼貌的吻别 2020-12-17 05:08

I have exactly 100 Sensors each \"measuring\" own data. I have exactly one DataSender which should send information from \"sensors\". The most recent information sh

2条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-17 05:57

    I think you should implement your own IProducerConsumerCollection. That's why it's an interface: so that you could easily make your own.

    You could do it using Dictionary and Queue to make sure receiving the data is fair, i.e. if you have just one device that produces data very fast, you won't send data just from this one.

    public class DeviceDataQueue
        : IProducerConsumerCollection>
    {
        private readonly object m_lockObject = new object();
        private readonly Dictionary m_data
            = new Dictionary();
        private readonly Queue m_queue = new Queue();
    
        //some obviously implemented methods elided, just make sure they are thread-safe
    
        public int Count { get { return m_queue.Count; } }
    
        public object SyncRoot { get { return m_lockObject; } }
    
        public bool IsSynchronized { get { return true; } }
    
        public bool TryAdd(Tuple item)
        {
            var device = item.Item1;
            var data = item.Item2;
    
            lock (m_lockObject)
            {
                if (!m_data.ContainsKey(device))
                    m_queue.Enqueue(device);
    
                m_data[device] = data;
            }
    
            return true;
        }
    
        public bool TryTake(out Tuple item)
        {
            lock (m_lockObject)
            {
                if (m_queue.Count == 0)
                {
                    item = null;
                    return false;
                }
    
                var device = m_queue.Dequeue();
                var data = m_data[device];
                m_data.Remove(device);
                item = Tuple.Create(device, data);
                return true;
            }
        }
    }
    

    When used along these lines:

    Queue = new BlockingCollection>(
        new DeviceDataQueue());
    
    Device1 = new Device(1, TimeSpan.FromSeconds(3), Queue);
    Device2 = new Device(2, TimeSpan.FromSeconds(5), Queue);
    
    while (true)
    {
        var tuple = Queue.Take();
        var device = tuple.Item1;
        var data = tuple.Item2;
    
        Console.WriteLine("{0}: Device {1} produced data at {2}.",
            DateTime.Now, device.Id, data.Created);
    
        Thread.Sleep(TimeSpan.FromSeconds(2));
    }
    

    it produces the following output:

    30.4.2011 20:40:43: Device 1 produced data at 30.4.2011 20:40:43.
    30.4.2011 20:40:45: Device 2 produced data at 30.4.2011 20:40:44.
    30.4.2011 20:40:47: Device 1 produced data at 30.4.2011 20:40:47.
    30.4.2011 20:40:49: Device 2 produced data at 30.4.2011 20:40:49.
    30.4.2011 20:40:51: Device 1 produced data at 30.4.2011 20:40:51.
    30.4.2011 20:40:54: Device 2 produced data at 30.4.2011 20:40:54.
    

提交回复
热议问题