A very common pattern in CCR is the use of a result port. That means that you have a port you give (or get from) a method you want to call and that method will post a result on the result port. However sometimes a bug leads to a situation where no result is ever posted back. This can be very hard to detect of ju just use a standard result/exception portset. If you're in the DSS environment you know that each operation typically has a timeout that is handled by DSS but in CCR you need to deal with this yourself. I've previously mentioned that a SmartPort could be used. But this is what it would look like with a timeout:
1: private void DoSomething(SuccessFailurePort resultPort) 2: { 3: // never posts a response. 4: } 5: 6: private void CallingSomething(TimeSpan timeout) 7: { 8: var mre = new ManualResetEvent(false); 9: Exception error = null; 10: var resultPort = new SuccessFailurePort(); 11: var timeoutPort = new Port<DateTime>(); 12: Arbiter.Activate( 13: dispatcherQueue, 14: Arbiter.Choice( 15: Arbiter.Receive<SuccessResult>(false, resultPort, s => mre.Set()), 16: Arbiter.Receive<Exception>( 17: false, 18: resultPort, 19: e => 20: { 21: error = e; 22: mre.Set(); 23: }), 24: Arbiter.Receive( 25: false, 26: timeoutPort, 27: e => 28: { 29: error = new Exception("Timeout when waiting for DoSomething"); 30: mre.Set(); 31: }))); 32: Arbiter.Activate( 33: dispatcherQueue, 34: Arbiter.FromHandler(() => this.DoSomething(resultPort))); 35: dispatcherQueue.EnqueueTimer(timeout, timeoutPort); 36: mre.WaitOne(); 37: if (error != null) 38: { 39: throw error; 40: } 41: } 42: 43: [TestMethod] 44: public void UsingTimeoutToDetectWhenSomethingIsNotPostingBack() 45: { 46: try 47: { 48: this.CallingSomething(TimeSpan.FromSeconds(1)); 49: Assert.Fail("Expected exception to be thrown"); 50: } 51: catch (Exception e) 52: { 53: Assert.IsTrue(e.Message.Contains("Timeout")); 54: } 55: }
The lines to pay most attention to are lines 14 through 31.