So recently I was writing a method to be run in CCR that had an annoying bug. The method took a PortSet where the result (or exception) was to be posted. The problem was that under certain conditions noting was posted leaving the caller waiting forever for the result. So I started to wonder if something like a smart-pointer could be used... This is how a smart port for CCR could be implemented:
1: public class SmartPortBase : IDisposable
2: {
3: private bool havePosted = false;
4: private Action fallbackAction;
5:
6: public SmartPortBase(Action fallbackAction)
7: {
8: if (fallbackAction == null)
9: {
10: throw new ArgumentNullException("fallbackAction");
11: }
12:
13: this.fallbackAction = fallbackAction;
14: }
15:
16: public void Dispose()
17: {
18: if (!this.havePosted)
19: {
20: this.fallbackAction();
21: }
22: }
23:
24: protected void Post()
25: {
26: this.havePosted = true;
27: }
28: }
29:
30: public class SmartPort : SmartPortBase
31: {
32: private IPort port;
33:
34: public SmartPort(IPort port)
35: : this(port, new SmartPortException())
36: {
37: }
38:
39: public SmartPort(IPort port, Exception exception)
40: : this(port,
41: () => {
42: if (!port.TryPostUnknownType(exception))
43: throw exception;
44: })
45: {
46: }
47:
48: public SmartPort(IPort port, Action fallbackAction)
49: : base(fallbackAction)
50: {
51: this.port = port;
52: }
53:
54: public void Post(object obj)
55: {
56: base.Post();
57: this.port.PostUnknownType(obj);
58: }
59: }
!-->
And this is how you would use it:
1: using (var sp = new SmartPort(somePort)) 2: { 3: sp.Post(42); 4: }!-->
Naturally you could tweak the SmartPort to be a generic class to avoid the use of PostUnknownType. While this gives you a good message whenever you forget to post a result it relies on the developer to use this SmartPort everywhere needed and if you forget to use this SmartPort you're stuck with the initial problem leading to the introduction of SmartPort anyway.
So what is the alternative? In DSS you don't have this problem because DSS guarantees a result being posted; A timeout. So the alternative is to always have a timeout port. And you only need a timeout port at the top level of your call stack and that will catch any case of a result not being posted back. With a timeout port you'll definitely know what caused your code to fail so reproducing should be simple rather than the code just hanging waiting.
Hi,
I've run into the same problem when I've implement my DAL using CCR.
The SmartPort is good solution but as you say you have to use it everywhere and that's not so easy.
I hope the CCR team will create some kind of diagnostic tool, either inside or outside the plan-old-Port class to help find this problems.
Ido.