我试图扩展这个SO答案,使WCF客户端在瞬态网络故障时重试并处理其他需要重试的情况,例如身份验证过期。
问题:
需要处理哪些WCF异常,以及正确的处理方式是什么?
以下是我希望看到的几种示例技术,而不是或除了
- 在重试之前延迟X秒 - 关闭并重新创建New() WCF客户端。 释放旧的。 - 不要重试并重新抛出此错误 - 重试N次,然后抛出
由于一个人不太可能知道所有异常或解决方法,因此请分享您所知道的内容。 我将在下面的代码示例中汇总答案和方法。
需要处理哪些WCF异常,以及正确的处理方式是什么?
以下是我希望看到的几种示例技术,而不是或除了
proxy.abort()
:- 在重试之前延迟X秒 - 关闭并重新创建New() WCF客户端。 释放旧的。 - 不要重试并重新抛出此错误 - 重试N次,然后抛出
由于一个人不太可能知道所有异常或解决方法,因此请分享您所知道的内容。 我将在下面的代码示例中汇总答案和方法。
// 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://dev59.com/dnM_5IYBdhLWcg3wUxZB#1428238
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
throw e
中的e
。它会抛弃前面的整个堆栈跟踪,使得逻辑故障排除变成猜谜游戏。 - StingyJack