如何发布wcf服务关闭WCF连接

This site in other countries/regions:trackbacks-0
在客户端正确的关闭WCF连接!
如果你直接将客户端调用Close关闭,或者使用using语句,那你将是个悲剧,这点相信使用WCF的同志都知道的,因为ClientBase类的Close()方法被调用后,实际上是关闭了一个网络会话,并且会抛出异常!CommunicationException和TimeoutException!
这似乎违反常理,但确实发生了。因为一般来说Close函数都不会抛出异常。这个问题的解决办法是使用Try-Catch语句包含Close()方法,然后再异常处理中使用Abort函数释放资源!
同样,ClientBase类的IDisposable接口的实现函数Dispose方法中会调用Close函数,使用Reflector查看ClientBase&TChannel& 的代码便知
所以你使用using语句同样不能正确关闭WCF连接!而我们使用using语句就是为了不管发生什么情况,只要离开作用域之后,就会释放相关资源。而WCF的ClientBase类设计很明显违反了这一观念!简直是坑爹啊!
解决这一问题网上以后很多方案,首先说说微软的,也许是微软也意识到这一点,所以微软在提供的WCF示例程序中特意包含了一个叫做UsingUsing的示例,名字听起来有点怪
主要解决的方法是如下的代码
1 // This method shows the correct way to clean up a client, including catching the
// approprate Exceptions.
static void DemonstrateCleanupWithExceptions()
// Create a client
CalculatorClient client = new CalculatorClient();
// Demonstrate a successful client call.
Console.WriteLine("Calling client.Add(0.0, 0.0);");
double addValue = client.Add(0.0, 0.0);
Console.WriteLine("
client.Add(0.0, 0.0); returned {0}", addValue);
// Demonstrate a failed client call.
Console.WriteLine("Calling client.Divide(0.0, 0.0);");
double divideValue = client.Divide(0.0, 0.0);
Console.WriteLine("
client.Divide(0.0, 0.0); returned {0}", divideValue);
// Do a clean shutdown if everything works.
In this sample we do not end up
// here, but correct code should Close the client if everything was successful.
Console.WriteLine("Closing the client");
client.Close();
catch (CommunicationException e)
// Because the server suffered an internal server error, it rudely terminated
// our connection, so we get a CommunicationException.
Console.WriteLine("Got {0} from Divide.", e.GetType());
client.Abort();
catch (TimeoutException e)
// In this sample we do not end up here, but correct code should catch
// TimeoutException when calling a client.
Console.WriteLine("Got {0} from Divide.", e.GetType());
client.Abort();
catch (Exception e)
// In this sample we do not end up here.
It is best practice to clean up the
// client if some unexpected Exception occurs.
Console.WriteLine("Got unexpected {0} from Divide, rethrowing.", e.GetType());
client.Abort();
其实就是使用try-catch语句捕获关闭时的异常!试想要是每次都这样调用WCF服务将会是多么痛苦的一件事情!网上也有人使用Linq的Expression来解决这一问题
于是我借用函数式编程的思想,设计了一个使用lambda表达式来解决这一问题的方案!
关键的函数很简单,一看便知道是我是怎样设计的!
1 public static class SvcClient
public static void Invoke&TClient&(Action&TClient& act)
where TClient : System.ServiceModel.ICommunicationObject, new()
TClient client = new TClient();
act(client);
client.Close();
catch (municationException)
client.Abort();
catch (TimeoutException)
client.Abort();
catch (Exception)
client.Abort();
实际上这一设计的思想就是:将所有调用WCF服务的所有代码做为一个函数传入进来,然后我再内部使用try-catch语句包裹整个调用过程,这样就巧妙的将处理关闭连接异常的代码与实际调用过程分离开来!
函数的使用过程也比较方便
1 SvcClient.Invoke&Service1Client&(client =&
3   //在此处添加调用WCF的代码
代码看起来比较简洁优美,个人比较满意,而且不用再担心调用结束后不能正确关闭WCF连接,资源不能正确释放的问题了!
阅读(...) 评论()温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
态度决定一切----------
LOFTER精选
上面的WCF服务的配置文件,下面再贴一张客户端的配置
在客户端和服务器端根据以上的图片进行配置问题就解决了!
之所以产生这个错误,主要是因为wcf默认序列化的对象超过65535个,所以这里我们要修改他的默认值即可。那到底他这个65635是怎么计算的呢,请往下看。。
public class MyObject
public int A;
public int B;
public student C; //假设student对象里面有两个属性(非自定义)
如果wcf返回单个MyObject的话,那这里就是6个对象了,即对象个数+属性个数,如果属性又是自定义类型的话,又需要计算出里面到底有多少个属性。注意:一个MyObejct就是6个对象,那如果返回的是List&MyObject&呢,那一共有多少个对象呢?6*List&MyObject&集合个数&(即如果集合是2的话,那就有12个对象,集合是3的话,就有18个对象);这样大家就明白为什么会报上面那个错误了!
当然,出现“基础连接已经关闭,连接被意外关闭”这种情况不是说一定是返回的数据量超过序列化的默认值,也有可能是别的,所以我们在发现这个问题的时候,应该先确认是由什么原因为产生的错误,可以调试看看返回的数据量是不是过大,设置返回的集合小一些,是不是正常了,如果是的话,那就应该是这个问题。不知我表达清楚没有,不清楚的朋友可以留言。。。
嗯,看完的同学都是好同学。。
阅读(893)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'wcf 基础连接已经关闭,连接被意外关闭',
blogAbstract:'&&& 项目中在使用wcf返回数据时,发现一直报这个错误“基础连接已经关闭,连接被意外关闭”,经检查后,发现代码没有什么问题,只是一个简单的查询,调试的时候,发现返回的数据量比较大6000多个,后面在想,是不是数据量太大的原因,把返回的数据改少些,马上就成功了!那OK了,起码知道问题出在哪里。出现这个问题主要是因为接收的数据超过了wcf默认值,只需要在服务端(Wcf)修改一下配置文件还有客户端(wcf调用者)就OK了。下面看看怎么修改吧。。
blogTag:'wcf错误',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:4,
publishTime:9,
permalink:'blog/static/',
commentCount:1,
mainCommentCount:1,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'态度决定一切----------',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭 - 伍华聪 - 博客园
随笔 - 390, 文章 - 20, 评论 - 5880, 引用 - 20
在我们开发WCF项目的时候,常常会碰到一些莫名其妙的错误,有时候如果根据它的错误提示信息,一般很难定位到具体的问题所在,而由于WCF服务的特殊性,调试起来也不是那么方便,因此往往会花费不少时间来进行跟踪处理。本文介绍我在我在我的框架里面使用WCF服务的时候,出现的一个常见错误的处理方法,它的提示信息是:基础连接已经关闭: 连接被意外关闭。这种情况我碰到的有两种,一种是返回DataTable的时候出现的,一种是返回实体类类中带有枚举类型的情况,下面分别对它们的处理进行介绍。&
1、DataTable返回值出现错误
一般情况下,我们在设计WCF接口返回值的时候,都使用实体类或者实体类列表这种方式,但是有时候也可能需要返回一个DataTable的数据类型,如果按照下面的方式构造函数内容并返回,就可能出现错误。
/// &summary&
/// 根据查询条件,返回记录到DataTable集合中
/// &/summary&
/// &param name="condition"&查询条件&/param&
/// &param name="pagerInfo"&分页条件&/param&
/// &returns&&/returns&
[OperationContract]
DataTable FindToDataTableWithPager(string condition, ref PagerInfo pagerInfo);
实现函数,为了方便演示,填写了简单的测试代码。
/// &summary&
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// &/summary&
/// &param name="condition"&查询的条件&/param&
/// &param name="info"&分页实体&/param&
/// &returns&指定对象的集合&/returns&
public DataTable
FindToDataTableWithPager(string condition, ref PagerInfo pagerInfo)
//测试代码
DataTable dt = new DataTable();
dt.Columns.Add("Test");
for (int i = 0; i & 10; i++)
dt.Rows.Add(new object[] { "Test" + i });
测试的时候,会发现出现错误
如果你按照它的提示,你可能搔破头皮也不知道具体是哪里的问题,这个地方其实很有意思,就是因为序列号DataTable的时候,没有TableName导致的,如果把函数体的实现里面,为返回的DataTable对象的TableName属性赋值一个值就可以了。
/// &summary&
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// &/summary&
/// &param name="condition"&查询的条件&/param&
/// &param name="info"&分页实体&/param&
/// &returns&指定对象的集合&/returns&
FindToDataTableWithPager(string condition, ref PagerInfo pagerInfo)
//测试代码
DataTable dt = new DataTable();
dt.Columns.Add("Test");
for (int i = 0; i & 10; i++)
dt.Rows.Add(new object[] { "Test" + i });
dt.TableName = "test";
测试之后,就发现能够顺利执行了。
2、实体类中含有枚举类型导致的错误
&实体类定义,定义了一个枚举的对象ApplyStatus
/// &summary&
/// 流程申请单
/// &/summary&
[DataContract]
public class ApplyInfo : BaseEntity
/// &summary&
/// 当前状态(0:处理中,1:已完成,2:已退回,3:已撤消)(其它值为非法值)
/// &/summary&
[DataMember]
public virtual ApplyStatus Status
return this.m_S
this.m_Status =
枚举的定义一般情况如果设置如下代码:
/// &summary&
/// 表单当前处理状态。
/// 当前状态(0:处理中,1:已完成,2:已退回,3:已撤消)(其它值为非法值)
/// &/summary&
[DataContract]
public enum ApplyStatus
/// &summary&
/// 处理中 = 0
/// &/summary&
处理中 = 0,
/// &summary&
/// 已完成 = 1
/// &/summary&
已完成 = 1,
/// &summary&
/// 已退回 = 2
/// &/summary&
已退回 = 2,
/// &summary&
/// 已撤消 =3
/// &/summary&
已撤消 = 3
然后定义WCF服务接口和实现代码。
WCF接口定义
/// &summary&
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// &/summary&
/// &param name="condition"&查询的条件&/param&
/// &param name="info"&分页实体&/param&
/// &returns&指定对象的集合&/returns&
[OperationContract]
List&T& FindWithPager(string condition, ref PagerInfo info);
WCF服务接口实现
/// &summary&
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
/// &/summary&
/// &param name="condition"&查询的条件&/param&
/// &param name="info"&分页实体&/param&
/// &returns&指定对象的集合&/returns&
public List&ApplyInfo& FindWithPager(string condition, ref PagerInfo info)
return bll.FindWithPager(condition, info);
那么通过WCF服务获取这个对象的信息时候,就会出现错误:基础连接已经关闭: 连接被意外关闭
&出现错误的原因,是因为枚举类型序列化出现了错误,需要在枚举的值里面增加[EnumMember]的声明,如下所示。
[DataContract]
public enum ApplyStatus
/// &summary&
/// 处理中 = 0
/// &/summary&
[EnumMember]
处理中 = 0,
/// &summary&
/// 已完成 = 1
/// &/summary&
[EnumMember]
已完成 = 1,
/// &summary&
/// 已退回 = 2
/// &/summary&
[EnumMember]
已退回 = 2,
/// &summary&
/// 已撤消 =3
/// &/summary&
[EnumMember]
已撤消 = 3
再次编译运行并测试,最后的结果就是能够正常解析了。
以上就是我们在开发WCF的时候,经常碰到的一些错误的解决方式,希望大家在开发WCF并进行调用的时候,碰到类似的问题,能够很好解决问题,节省宝贵的时间。[WCF] 用WCF的TCP通道如何实现服务关闭和重启?
[问题点数:50分,结帖人lujiaxing2007]
[WCF] 用WCF的TCP通道如何实现服务关闭和重启?
[问题点数:50分,结帖人lujiaxing2007]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
本帖子已过去太久远了,不再提供回复功能。

我要回帖

更多关于 关闭的连接 的文章

 

随机推荐