Exception Handling

Causalities and Exception Ports

If you already have experience in handling exceptions with the CCR, you will see that with the AppSpace you can do it exactly the same way. Here is how it works: Exceptions are handled over so-called Causalities. A Causality is more or less a Port to which exceptions can be posted (the Exception Port). If an exception is thrown during the processing of a message, it will then be posted back to the exception port, from where you can handle it the way you like. So, the first thing you need to do is create an exception port:
Port<Exception> exceptionPort= new Port<Exception>();
space.Receive(exceptionPort, ex => ...handle exception...);
You then have two possibilities for using the exception port.
1. Using PostWithCausality
The first one is to post you messages not with the Post method but with the PostWithCausality method (which is an extension method for the Port class provided by the AppSpace):
worker.PostWithCausality(message, exceptionPort);
Note: This extension method is currently only available for Ports, as well as for PortSets with up to five ports. If you have a Worker with more than five ports, you can, however, still access the worker's ports directly and to something like worker.P0.PostWithCausality(...).
2. Using Dispatcher.AddCausality
The second possibility will sound very familiar to you, and could be the more convenient one if you want to post multiple messages using the same Causality. It is equal to the way you would normally do it with the CCR:
Causality c = new Causality ("c", exceptionPort);
Dispatcher.AddCausality(c);
...
worker.Post(msg1);
worker.Post(msg2);
worker.Post(msg3);
...
Dispatcher.RemoveCausality(c);
This way you create your causality manually, using the previously created exception port. By calling Dispatcher.AddCausality() you install the causality so that it will from this point on be used for every posted message, until you call Dispatcher.RemoveCausality(). For more infos on CCR Causalities you can also take a look at http://msdn.microsoft.com/en-us/library/bb648750.aspx.

With both of these possibilities your exception port will automatically transferred together with the posted message(s), and any exception that is thrown will be posted to the exception port. This also includes exceptions that are thrown if there is an error during message transfer or serialization/deserialization.

Handling communication errors with Send()

When using remote communication, a typical scenario is that you want to ensure that your message has been delivered successfully if before you go on with processing. This is difficult with just using causalities, as they don't provide you with a message saying "message sent sucessfully". Therefore we provide an extension method for the Port/PortSet class called Send(). This method will send a message synchronously and directly throw an exception if something goes wrong while sending the message (e.g. when the other space cannot be reached).
try
{
   worker.Send(message);
}
catch (Exception ex)
{
   Console.WriteLine("ERROR: " + ex.Message);
}
The Send() method is also very helpful in Situations where you need to send a last message directly before disposing a AppSpace instance (e.g. for unsubscribing yourself from another worker) - if you would do that with Post() there would be no guarantee that the message is actually transferred before the AppSpace is disposed.

The XcoAppSpace errors port

The XcoAppSpace class also provides a property called Errors, which is of Type Port<XcoCommunicationError>. To this port all errors are posted that occur between a Post() call and the arrival of the posted message at its target worker/port, if there are no causalities installed. So, this port should help you recognize errors when you didn't expect them. The XcoCommunicationError class includes an as detailed as possible description to tell you what went wrong. The possible errors that are posted to the exception port include:
  • Serialization/Deserialization Errors (e.g. your class is not marked as serializable, or threw an exception during the serialization/deserialization process)
  • Errors during Message Transfer (e.g. the target space cannot be reached)
A simple routine for outputting errors from the errors port could look something like this:
space.Receive(space.Errors, e => Console.WriteLine("Unexpected error: {0} - Source: {1} - Exception: {2}", e.Info, e.SourceAddress, e.Error.Message));

Last edited Jun 21, 2010 at 1:04 PM by thomass, version 9

Comments

No comments yet.