Recuperação de uma CommunicationObjectFaultedException no WCF
Pergunta
Eu tenho um aplicativo cliente que tenta a cada 10 segundos para enviar uma mensagem através de um serviço WCF web. Este aplicativo cliente será em um computador a bordo de um navio, que sabemos que vai ter conectividade com a Internet irregular. Eu gostaria que o aplicativo tentar enviar dados através do serviço, e, se não puder, fazer fila as mensagens até que ele possa enviá-los através do serviço.
Para testar esta configuração, eu iniciar o aplicativo cliente e o serviço web (tanto na minha máquina local), e tudo funciona bem. Eu tento simular a má ligação à internet por matar o serviço web e reiniciá-lo. Assim que eu matar o serviço, eu começar a receber CommunicationObjectFaultedExceptions - que é esperado. Mas depois que eu reiniciar o serviço, eu continuo a obter essas exceções.
Eu tenho certeza de que há algo que eu não estou entendendo sobre o paradigma dos serviços web, mas eu não sei o que é. Alguém pode oferecer conselhos sobre se deve ou não essa configuração é viável, e em caso afirmativo, como resolver este problema (ou seja, re-estabelecer o canal de comunicação com o serviço web)?
Obrigado!
Klay
Solução
proxies de serviço do cliente não pode ser reutilizado depois de terem criticado. Você deve descartar o velho e recriar uma nova.
Você também deve certificar-se de fechar o proxy de serviço cliente corretamente. É possível para um proxy de serviço WCF para lançar uma exceção no próximo, e se isso acontecer, a conexão não está fechado, então você deve abortar. Use o "try {Fechar} / catch {Abortar}" padrão. Também tenha em mente que o método dispose chama perto (e, portanto, pode lançar uma exceção do descarte), para que você não pode apenas usar um usando como com aulas de escoamento normal.
Por exemplo:
try
{
if (yourServiceProxy != null)
{
if (yourServiceProxy.State != CommunicationState.Faulted)
{
yourServiceProxy.Close();
}
else
{
yourServiceProxy.Abort();
}
}
}
catch (CommunicationException)
{
// Communication exceptions are normal when
// closing the connection.
yourServiceProxy.Abort();
}
catch (TimeoutException)
{
// Timeout exceptions are normal when closing
// the connection.
yourServiceProxy.Abort();
}
catch (Exception)
{
// Any other exception and you should
// abort the connection and rethrow to
// allow the exception to bubble upwards.
yourServiceProxy.Abort();
throw;
}
finally
{
// This is just to stop you from trying to
// close it again (with the null check at the start).
// This may not be necessary depending on
// your architecture.
yourServiceProxy = null;
}
Há um artigo no blog sobre este aqui