Share via


CCR tips and tricks - part 3

Causalities are very powerful in CCR. It's essentially an unhandled exception handler that travels with your messages as you post them. That is; once a causality is added it will travel with your message if posted to a port and even be applied to any spawned tasks. A very typical way to use causalities is to add them as you enter a major service/component. If you add multiple causalities the last one added will be called first and then removed from the causality stack. Here is an example on how to setup causalities.

  1:     [TestClass]
 2:     public class Given_a_causality_when_unhandled_exception_is_thrown
 3:     {
 4:         private DispatcherQueue dispatcherQueue = new DispatcherQueue();
 5:         private Exception causalityException = null;
 6:         private string exceptionMessage = "My unhandled exception";
 7:  
 8:         [TestInitialize]
 9:         public void Setup()
 10:         {
 11:             var mre = new ManualResetEvent(false);
 12:             Port<Exception> exceptionPort = new Port<Exception>();
 13:             Causality causality = new Causality(
 14:                 string.Format("CausalityForTests: {0}", Guid.NewGuid()), 
 15:                 exceptionPort);
 16:             Arbiter.Activate(dispatcherQueue, exceptionPort.Receive(
 17:                 (e) =>
 18:                 {
 19:                     causalityException = e;
 20:                     mre.Set();
 21:                 }));
 22:             Dispatcher.AddCausality(causality);
 23:  
 24:             Arbiter.Activate(dispatcherQueue, 
 25:                 Arbiter.FromHandler(() => Arbiter.Activate(dispatcherQueue, 
 26:                     Arbiter.FromHandler(() =>
 27:                         {
 28:                             throw new Exception(exceptionMessage);
 29:                         }))));
 30:             Assert.IsTrue(
 31:                 mre.WaitOne(TimeSpan.FromSeconds(5)), 
 32:                 "Causality did not get exception");
 33:         }
 34:  
 35:         [TestMethod]
 36:         public void Then_exception_is_handled_by_causality()
 37:         {
 38:             Assert.IsNotNull(causalityException);
 39:             Assert.AreEqual(exceptionMessage, causalityException.Message);
 40:         }
 41:     }

Four simple steps. Create an exception port, register a receiver on it, create a causality with that port and add the causality. Note that if the handling port is persistent you may get multiple exceptions if your task spawns multiple tasks where more than one throw an unhandled exception. So remember, causalities are to be used to handle unhandled exceptions, not to handle errors.