CCR tips and tricks - part 11
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.