J'essaie d'étendre cette réponse sur SO pour faire un client de WCF réessayer sur les échecs transitoires de réseau et manipuler d'autres situations qui nécessitent une nouvelle tentative, comme l'expiration de l'authentification.
Question :
Quelles sont les exceptions WCF qui doivent être traitées, et quelle est la manière correcte de les traiter ?
Voici quelques exemples de techniques que j'espère voir remplacer ou compléter proxy.abort()
:
- Délai de X secondes avant la nouvelle tentative
- Fermez et recréez un client WCF New(). Déposez l'ancien client.
- Ne pas réessayer et rejeter cette erreur.
- Réessayez N fois, puis lancez
Comme il est peu probable qu'une seule personne connaisse toutes les exceptions ou les moyens de les résoudre, partagez ce que vous savez. Je vais regrouper les réponses et les approches dans l'exemple de code ci-dessous.
// USAGE SAMPLE
//int newOrderId = 0; // need a value for definite assignment
//Service<IOrderService>.Use(orderService=>
//{
// newOrderId = orderService.PlaceOrder(request);
//}
/// <summary>
/// A safe WCF Proxy suitable when sessionmode=false
/// </summary>
/// <param name="codeBlock"></param>
public static void Use(UseServiceDelegateVoid<T> codeBlock)
{
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
catch (CommunicationObjectAbortedException e)
{
// Object should be discarded if this is reached.
// Debugging discovered the following exception here:
// "Connection can not be established because it has been aborted"
throw e;
}
catch (CommunicationObjectFaultedException e)
{
throw e;
}
catch (MessageSecurityException e)
{
throw e;
}
catch (ChannelTerminatedException)
{
proxy.Abort(); // Possibly retry?
}
catch (ServerTooBusyException)
{
proxy.Abort(); // Possibly retry?
}
catch (EndpointNotFoundException)
{
proxy.Abort(); // Possibly retry?
}
catch (FaultException)
{
proxy.Abort();
}
catch (CommunicationException)
{
proxy.Abort();
}
catch (TimeoutException)
{
// Sample error found during debug:
// The message could not be transferred within the allotted timeout of
// 00:01:00. There was no space available in the reliable channel's
// transfer window. The time allotted to this operation may have been a
// portion of a longer timeout.
proxy.Abort();
}
catch (ObjectDisposedException )
{
//todo: handle this duplex callback exception. Occurs when client disappears.
// Source: https://stackoverflow.com/questions/1427926/detecting-client-death-in-wcf-duplex-contracts/1428238#1428238
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}