我有一个wcf服务,以及相应的客户端。当服务出现故障时,从客户端到服务的每次调用都会抛出异常。但我需要客户端重新连接,所以我将客户端包装到异常处理程序中并重新连接。 实现自动重新连接行为的首选方法是什么? 我的客户:
internal sealed class BloombergClient
{
#region Singleton
private static Lazy<BloombergClient> instance = new Lazy<BloombergClient>(() => new BloombergClient(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
public static BloombergClient Instance { get { return instance.Value; } }
#endregion
private readonly ExceptionReconnectHandler exceptionHandler;
private readonly Object lockObject = new Object();
private readonly ManualResetEventSlim eventSlim = new ManualResetEventSlim(true);
private BloombergModuleServiceClient client;
private volatile Boolean isConnecting;
public event System.EventHandler ConnectionEstablished;
private BloombergClient()
{
this.exceptionHandler = new ExceptionReconnectHandler(HandleException);
Connect();
}
//Example method
public Double GetDailyClose(String bloombergTicker, DateTime date)
{
eventSlim.Wait();
return exceptionHandler.Execute(() => this.client.GetDailyClose(bloombergTicker, date));
}
private void HandleException(Exception e)
{
Connect();
}
private void BloombergServiceClientFaulted(object sender, EventArgs e)
{
Connect();
}
private Boolean CreateClient()
{
Boolean init = false;
if (this.client != null)
{
((ICommunicationObject)client).Faulted -= BloombergServiceClientFaulted;
((ICommunicationObject)client).Closed -= BloombergServiceClientFaulted;
}
this.client = new BloombergModuleServiceClient();
if (this.client.State == CommunicationState.Created)
{
((ICommunicationObject)client).Faulted += BloombergServiceClientFaulted;
((ICommunicationObject)client).Closed += BloombergServiceClientFaulted;
init = true;
}
else
{
init = false;
}
return init;
}
private void Connect()
{
lock (this.lockObject)
{
if (isConnecting) return;
lock (this.lockObject)
{
if (isConnecting) return;
isConnecting = true;
}
}
//if (eventSlim.IsSet) return; - offcourse not working
eventSlim.Reset();
try
{
while (true)
{
try
{
if (client != null && client.State == CommunicationState.Opened)
{
((ICommunicationObject)client).Abort();
}
if (CreateClient())
{
break;
}
}
catch (Exception e)
{
Log.Instance.WriteLineT(e.Message, "Bloomberg Client");
}
Thread.Sleep(1000);
}
}
finally
{
eventSlim.Set();
isConnecting = false;
ConnectionEstablished.Raise(this);
}
}
}
public class ExceptionReconnectHandler
{
private readonly Action<Exception> handler;
public ExceptionReconnectHandler(Action<Exception> handler)
{
if (handler == null) throw new ArgumentNullException("handler");
this.handler = handler;
}
public virtual T Execute<T>(Func<T> func)
{
if (func == null) throw new ArgumentNullException("func");
while (true)
{
try
{
return func();
}
catch (Exception e)
{
handler(e);
}
}
}
public virtual void Execute(Action action)
{
if (action == null) throw new ArgumentNullException("action");
while (true)
{
try
{
action();
return;
}
catch (Exception e)
{
handler(e);
}
}
}
}