Rx operator to distinct sequences

后端 未结 3 1975
后悔当初
后悔当初 2021-02-20 17:23

IMPORTANT: for a description of the results and some more details, please have a look also to my answer

I need to group and filter a sequence of objects

3条回答
  •  一个人的身影
    2021-02-20 18:26

    After searches and experiments, I put together some code that produces the output that I expect:

    static void Main(string[] args)
        {
            const string Address1 = "A:2.1.1";
            const string Address2 = "A:2.1.2";
            var comparer = new EventComparer();
            var eventMessageA1 = new EventMessage { NetworkAddress = Address1, EventCode = 1, Attribute = 4 };
            var eventMessageB1 = new EventMessage { NetworkAddress = Address2, EventCode = 1, Attribute = 5 };
            var eventMessageA2 = new EventMessage { NetworkAddress = Address1, EventCode = 1, Attribute = 5 };
            var list = new[] { eventMessageA1, eventMessageA1, eventMessageB1, eventMessageA2, eventMessageA1, eventMessageA1 };
    
            var queue = new BlockingCollection();
            Observable.Interval(TimeSpan.FromSeconds(2)).Subscribe
                (
                    l => list.ToList().ForEach(m =>
                    {
                        Console.WriteLine("Producing {0} on thread {1}", m, Thread.CurrentThread.ManagedThreadId);
                        queue.Add(m);
                    })
                );
    
            // subscribing
            queue.GetConsumingEnumerable()
                .ToObservable()
                 .Buffer(TimeSpan.FromSeconds(5))
                 .Subscribe(e =>
                     {
                         Console.WriteLine("Queue contains {0} items", queue.Count);
                         e.Distinct(comparer).ToList().ForEach(m =>
                      Console.WriteLine("{0} - Consuming: {1} (queue contains {2} items)", DateTime.UtcNow, m, queue.Count));
                     }
                 );
    
            Console.WriteLine("Type enter to exit");
            Console.ReadLine();
        }
    
        public class EventComparer : IEqualityComparer
        {
            public bool Equals(EventMessage x, EventMessage y)
            {
                var result = x.NetworkAddress == y.NetworkAddress && x.EventCode == y.EventCode && x.Attribute == y.Attribute;
                return result;
            }
    
            public int GetHashCode(EventMessage obj)
            {
                var s = string.Concat(obj.NetworkAddress + "_" + obj.EventCode + "_" + obj.Attribute);
                return s.GetHashCode();
            }
        }
    
        public class EventMessage
        {
            public string NetworkAddress { get; set; }
    
            public byte EventCode { get; set; }
    
            public byte Attribute { get; set; }
    
            public override string ToString()
            {
                const string Format = "{0} ({1}, {2})";
                var s = string.Format(Format, this.NetworkAddress, this.EventCode, this.Attribute);
                return s;
            }
        }
    

    Anyway, monitoring the application, it seems that this causes a memory leak. My question is now:

    • what is causing the memory leak? [please see the update below]
    • is this the best way to do it (if I put the distinct on the first observable, I don't get the other events on next buffers, but items in each buffer should be isolated from others)?
    • how can I write a test using the test scheduler?

    UPDATE:

    it seems that the memory increment lasts only some minutes, then the value is stable. I will run a long test. Of course, this would be an absolutely acceptable behavior.

    UPDATE 26.08.12:

    • as I already mentioned in the previous update, the memory usage increases only (and slowly) for some minutes after the startup. After 8 hours the memory consumed was stable, with normal fluctuations in the range of few KB)
    • this question is very similar to mine and the suggested Drain extension could apply well to my problem (still to be verified)

    Anyway, I think that my question is still open for unit tests using the test scheduler.

    thanks Francesco

提交回复
热议问题