Эта проблема также может возникать из-за того, что клиент WCF не очищается, когда вы его используете. В нашей системе мы используем одноразовый шаблон вместе с упаковкой всех вызовов функций в систему, чтобы обеспечить надлежащую очистку и ведение журнала. Мы используем версию следующего класса:
public class WcfWrapper : IDisposable
{
private readonly OperationContextScope _operationContextScope;
private readonly IClientChannel _clientChannel;
public WcfWrapper(IClientChannel clientChannel)
{
_clientChannel = clientChannel;
_operationContextScope = new OperationContextScope(_clientChannel);
}
public void Dispose()
{
_operationContextScope.Dispose();
}
public T Function<T>(Func<T> func)
{
try
{
var result = func();
_clientChannel.Close();
return result;
}
catch (Exception ex)
{
KTrace.Error(ex);
_clientChannel.Abort();
throw;
}
}
public void Procedure(Action action)
{
try
{
action();
_clientChannel.Close();
}
catch (Exception ex)
{
KTrace.Error(ex);
_clientChannel.Abort();
throw;
}
}
}
}
Каждый вызов WCF, который мы делаем в нашем сервисе, осуществляется через определенный класс интерфейса, подобный следующему:
public sealed class WcfLoginManager : ILoginManager
{
private static LoginManagerClient GetWcfClient()
{
return
new LoginManagerClient(
WcfBindingHelper.GetBinding(),
WcfBindingHelper.GetEndpointAddress(ServiceUrls.LoginManagerUri));
}
public LoginResponse Login(LoginRequest request)
{
using(var loginManagerClient = GetWcfClient())
using (var slice = new WcfWrapper(loginManagerClient.InnerChannel))
{
DSTicket ticket;
DSAccount account;
return slice.Function(() => new LoginResponse(loginManagerClient.Login(request.accountName, request.credentials, out ticket, out account), ticket, account));
}
}
}
Используя этот шаблон, все вызовы WCF в систему переносятся либо с помощью метода Function, либо с помощью процедуры, позволяющей им сначала убедиться, что ведение журнала происходит при всех ошибках, и, во-вторых, обеспечить закрытие канала, когда ошибки не возникают, но прерываются, если исключение случается. Наконец, как указано в операторе using, вызывается окончательное удаление канала. Таким образом, ошибки, возникающие из-за неправильной очистки каналов, которые будут выглядеть как эта ошибка, будут предотвращены.