C# ChannelFactory与自动生成代理中的错误处理
我最近开始编写自己的ChannelFactory包装器来调用我的WCF服务,而不是依赖于VisualStudio自动生成的代码 以前,通过自动生成的代理,我可以执行以下错误检查:C# ChannelFactory与自动生成代理中的错误处理,c#,.net,wcf,proxy,channelfactory,C#,.net,Wcf,Proxy,Channelfactory,我最近开始编写自己的ChannelFactory包装器来调用我的WCF服务,而不是依赖于VisualStudio自动生成的代码 以前,通过自动生成的代理,我可以执行以下错误检查: protected AccessControlServiceClient AccessControlService { get { // Check if not initialized yet if (HttpContex
protected AccessControlServiceClient AccessControlService
{
get
{
// Check if not initialized yet
if (HttpContext.Current.Session["AccessControlServiceClient"] == null)
HttpContext.Current.Session["AccessControlServiceClient"] = new AccessControlServiceClient();
// If current client is 'faulted' (due to some error), create a new instance.
var client = HttpContext.Current.Session["AccessControlServiceClient"] as AccessControlServiceClient;
if (client.State == CommunicationState.Faulted)
{
try { client.Abort(); }
catch { /* no action */ }
client = new AccessControlServiceClient();
HttpContext.Current.Session["AccessControlServiceClient"] = client;
}
return client;
}
}
我应该如何处理这个问题?如果出现问题,需要处理和重新创建渠道的最佳实践是什么?e、 例如,间歇性网络连接、会话超时等
这就是我的代码当前的样子:
ProxyBase.cs中的代码段-创建通道
private void Initialise()
{
lock (_sync)
{
if (_channel != null) return;
_channel = new ChannelFactory<T>(_serviceEndPointUri).CreateChannel();
}
}
因此,目前,每当默认的10分钟会话启动时,我都会收到一个错误,因为通道已经关闭
如何强化代码,使其能够处理网络断开/会话超时等问题?在我当前的项目中,我为客户端创建了一个包装类,它使用
CurrentInstance
访问器模型。getter检查\u client.State
是否有关闭
、关闭
或故障
,并在这种情况下创建新的客户端。创建新客户机是由提供给包装构造函数的工厂委托完成的,因此有一种自由但一致的方法来创建客户机实例
对于您的场景,这意味着将包装器存储在会话中,而不是直接存储客户机。调用wrapper.CurrentInstance
将检查状态,如果同时发生超时,将在后台重新创建客户端
该模型还可以方便地扩展为健壮的错误处理(用于物理断开连接、服务器崩溃…、延迟初始化、创建新客户端后的任意初始化逻辑(在我的例子中,它调用了某种Subscribe
方法,创建回调通道,但它可以是任何东西)
我希望这可能也是您的正确方向。我使用这样的代码
public T Channel {
get {
lock (_channelLock) {
if (!object.Equals(_channel, default(T))) {
if (((ICommunicationObject)_channel).State == CommunicationState.Faulted) {
// channel has been faulted, we want to create a new one so clear it
_channel = default(T);
}
}
if (object.Equals(_channel, default(T))) {
// channel is null, create a new one
Debug.Assert(_channelFactory != null);
_channel = _channelFactory.CreateChannel();
}
return _channel;
}
}
我通常在每个操作中使用一个新的服务实例。像这样:
public async Task<bool> IsOnline()
{
using (var service = new DebugService())
{
return await service.OnlineCheckAsync();
}
}
事实上,我在编辑中强调了这一点。不过,链接中可用的代码现在已在答案中。
public T Channel {
get {
lock (_channelLock) {
if (!object.Equals(_channel, default(T))) {
if (((ICommunicationObject)_channel).State == CommunicationState.Faulted) {
// channel has been faulted, we want to create a new one so clear it
_channel = default(T);
}
}
if (object.Equals(_channel, default(T))) {
// channel is null, create a new one
Debug.Assert(_channelFactory != null);
_channel = _channelFactory.CreateChannel();
}
return _channel;
}
}
public async Task<bool> IsOnline()
{
using (var service = new DebugService())
{
return await service.OnlineCheckAsync();
}
}
public void Dispose()
{
// The following code is from: http://www.vasylevskyi.com/2010/11/correct-wcf-client-proxy-closing.html
try
{
if (this.State != CommunicationState.Closed && this.State != CommunicationState.Faulted)
{
((ICommunicationObject)this).BeginClose(
(asr) =>
{
try
{
((ICommunicationObject)this).EndClose(asr);
}
catch
{
this.Abort();
}
}, null
);
}
else
{
this.Abort();
}
}
catch (CommunicationException)
{
this.Abort();
}