CCR tips and tricks - part 20

In robotics you sometimes work with a sensor that sends data very often but you really just want to handle one message every X seconds. You also just want to handle the last message received since you last handled a message. This can be achieved in a similar way to the resource port in part 19 together with a simple loop to drain a port of events.

   1: [TestMethod]
  2: public void BasedOnTimeWithMessagesDroped()
  3: {
  4:     var timePort = new Port<DateTime>();
  5:     var eventPort = new Port<int>();
  6:     var resultPort = new Port<int>();
  7:  
  8:     Arbiter.Activate(
  9:         dispatcherQueue,
 10:         Arbiter.JoinedReceive(
 11:         true,
 12:         timePort,
 13:         eventPort,
 14:         (timer, eventValue) =>
 15:             {
 16:                 try
 17:                 {
 18:                     int valueToUse = eventValue;
 19:                     int v;
 20:                     while (eventPort.Test(out v))
 21:                     {
 22:                         valueToUse = v;
 23:                     }
 24:                     resultPort.Post(valueToUse);
 25:                 }
 26:                 finally
 27:                 {
 28:                     dispatcherQueue.EnqueueTimer(
 29:                         TimeSpan.FromMilliseconds(100), 
 30:                         timePort);
 31:                 }
 32:             }));
 33:     dispatcherQueue.EnqueueTimer(TimeSpan.FromMilliseconds(100), timePort);
 34:     for (int i = 0; i < 100; i++)
 35:     {
 36:         Thread.Sleep(TimeSpan.FromMilliseconds(10));
 37:         eventPort.Post(i);
 38:     }
 39:     var mre = new ManualResetEvent(false);
 40:     int result = 0;
 41:     Arbiter.Activate(
 42:         dispatcherQueue,
 43:         resultPort.Receive(
 44:             r =>
 45:                 {
 46:                     result = r;
 47:                     mre.Set();
 48:                 }));
 49:     Assert.IsTrue(mre.WaitOne(TimeSpan.FromSeconds(3)));
 50:     Assert.AreNotEqual(0, result);
 51:     Assert.AreNotEqual(99, result);
 52: }

Like with the resource port it is important always enqueue a new timer (line 28+). The code to drain a port and preserve only the last value is line 19 to 23.