CCR tips and tricks - part 13

Another very common misunderstanding is that the Receive with no arguments is the same as using an empty handler. That is not true; when you yield return with the argumentless receive your method will wait for something to arrive on the port but it will not remove the item from the port. Here are two tests to illustrate the difference:

   1: private IEnumerator<ITask> SimpleDoubleEmptyReceiver(
  2:     Port<EmptyValue> port, 
  3:     ManualResetEvent mre)
  4: {
  5:     yield return port.Receive(CcrServiceBase.EmptyHandler);
  6:     yield return port.Receive(CcrServiceBase.EmptyHandler);
  7:     mre.Set();
  8: }
  9:  
 10: [TestMethod]
 11: public void UsingSimpleEmptyReceive()
 12: {
 13:     var mre = new ManualResetEvent(false);
 14:     var port = new Port<EmptyValue>();
 15:     Arbiter.Activate(
 16:         dispatcherQueue, 
 17:         Arbiter.FromIteratorHandler(
 18:             () => this.SimpleDoubleEmptyReceiver(port, mre)));
 19:     port.Post(EmptyValue.SharedInstance);
 20:     Assert.IsFalse(
 21:         mre.WaitOne(TimeSpan.FromSeconds(5)), 
 22:         "Processing completed in time");
 23: }
 24:  
 25: private IEnumerator<ITask> SimpleDoubleReceiver(
 26:     Port<EmptyValue> port, 
 27:     ManualResetEvent mre)
 28: {
 29:     yield return port.Receive();
 30:     yield return port.Receive();
 31:     mre.Set();
 32: }
 33:  
 34: [TestMethod]
 35: public void UsingSimpleReceive()
 36: {
 37:     var mre = new ManualResetEvent(false);
 38:     var port = new Port<EmptyValue>();
 39:     Arbiter.Activate(
 40:         dispatcherQueue, 
 41:         Arbiter.FromIteratorHandler(
 42:             () => this.SimpleDoubleReceiver(port, mre)));
 43:     port.Post(EmptyValue.SharedInstance);
 44:     Assert.IsTrue(
 45:         mre.WaitOne(TimeSpan.FromSeconds(5)), 
 46:         "Processing failed to complete in time");
 47: }

This difference can be deceiving if you reuse a port and the purpose is to use it in a spawn and test type scenario.