If you need to have two Silverlight apps talking to each other, you would be using the LocalMessageSender and LocalMessageReceiver classes from the System.Windows.Messaging namespace. The problem with the LocalMessageSender is that it might not be able to send message at the very first try. So you will have to write code which retries to send the message for an x number of times. Rather than duplicating this code all over the place, I decided to create a class which will do this for you.
using System; using System.Windows.Messaging; namespace Common { public class RetryMessageSender { private readonly int maxRetryCount; private LocalMessageSender messageSender; private int retryCount = 1; public event EventHandler<SendCompletedEventArgs> SendCompleted; public RetryMessageSender(LocalMessageSender messageSender) : this(messageSender, 100 /*default value of max retries*/) { } public RetryMessageSender(LocalMessageSender messageSender, int maxRetries) { this.messageSender = messageSender; this.maxRetryCount = maxRetries; messageSender.SendCompleted += new System.EventHandler<SendCompletedEventArgs>(messageSender_SendCompleted); } public void SendMessage(string msg) { messageSender.SendAsync(msg); } void messageSender_SendCompleted(object sender, SendCompletedEventArgs e) { if (e.Error != null) { if (retryCount <= maxRetryCount) { retryCount++; SendMessage(e.Message); } else { SendCompleted(sender, e); } } else { retryCount = 0; SendCompleted(sender, e); } } } }
Now you can use this class like this:
RetryMessageSender msgSender = new RetryMessageSender(messageSender, 10); msgSender.SendCompleted += new System.EventHandler<SendCompletedEventArgs>(msgSender_SendCompleted); msgSender.SendMessage("hello");
In the SendCompleted event handler, you can check whether the message was sent successfully within the specified number of retries (10 in this case).
static void msgSender_SendCompleted(object sender, SendCompletedEventArgs e) { if (e.Error != null) { throw new System.Exception("Unable to send message even after 10 retries"); } }
Few notes:
1. Can RetryMessageSender be implemented as a decorator of LocalMessageSender? I mean, can the client program against an interface without knowing if retrying decorator is added or not?
2. Instead of blind retries, would you want something more sophisticated like a circuit breaker? See http://timross.wordpress.com/2008/02/10/implementing-the-circuit-breaker-pattern-in-c/
3. What is the method naming standard in C#? I am curious about method names like messageSender_SendCompleted which are bothCamelCase_andDashed
Good comments mashe. Thanks for the insights.
1. Yes I think that can be done. I will try to make the changes and post the code.
2. Don’t you think the maxRetryCount works like a circuit breaker ?
3. Generally methods are PascalCased in C#. The method that you specified is an eventhandler and the convention for an event handler is object_EventName. Here the object that raises the event is messageSender and the event is SendCompleted. So Visual Studio by default will create a method named messageSender_SendCompleted. It is an inconsistency, I agree, but I think people are used to seeing this in C#.