wcf 客户端 同时多次访问服务器一般会卡住,为什么?

dqy007 2010-01-07 03:20:47
如:客户端打开一个窗口,窗口初始化的时候, 可能要到服务器读一此绑定的数据,放在下拉框中,但是下拉框有个选择事件,它又会访问数据库读一些别的信息,这时候一般就会卡住。两次访问服务器之间的时间太短,我的程序是这样写的,
第一次访问服务器
1、打开通道
2、读数据库
3、关闭通道

第二次访问服务器
1、打开通道
2、读数据库
3、关闭通道

我目前 猜 的可能原因是不是,第一次刚刚关闭通道,在很短的时间里又打开通道就会卡住 ???
...全文
1394 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
hjzhou 2011-07-18
  • 打赏
  • 举报
回复
qldsrx,最后如何解决这问题?
dqy007 2010-01-09
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 cczdp 的回复:]
1. 你的程序设计首先有问题,当你加载所有项的时候,不要触发改变事件。解决方案是设置一个开关变量,当加载的时候变量为false,加载完设置为true;在下拉框改变事件中判断是true才处理。
2. wcf不会卡,我们做压力测试2000个用户并发访问都没有问题,何况你一个用户,应该是你的调用wcf的代码部分有问题,但是没有代码,不好说什么问题。
[/Quote]

我说的WCF卡,不是后台WCF服务卡,而且客户端程序卡,这个我已经跟踪过了,不是网络问题,不是服务器问题,,
dqy007 2010-01-09
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 qldsrx 的回复:]
引用 15 楼 dqy007 的回复:
我的服务器过程契约是这样的[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)],这种有没有问题

你添加InstanceContextMode = InstanceContextMode.PerCall后,ConcurrencyMode = ConcurrencyMode.Multiple是没有意义的,PerCall模式不需要设置ConcurrencyMode,肯定是每个访问独立的。
引用 21 楼 dqy007 的回复:
不是不知道怎么处理出错,意思是再次用到这个实例之前要判断是否有效,但是这个实例没有属性能提示它失效了还是在连接状态,

PerCall模式下,没有连接与断开的概念,如果你客户端创建了与服务器端的一个连接实例,就全局保存它吧,因为那个实例永远不可能失效,即使客户端将网线拔掉,检查它的连接状态仍旧是已经连着的状态,不会显示为断开状态,除非自己手动去关闭连接。
至于检测连接状态,找到你创建的ChannelFactory <IServer>对象,ChannelFactory <IServer>.State属性就是连接状态。
[/Quote]
下面我的确碰到这个问题,网线拨掉,那个状态还是打开的,就是因为这点,反而麻烦,无法检查 是否真得断掉了,

我想问一下,你们平时做这个程序,是用一次服务,后面就关掉它,,,还是在程序一开始就搞个全局实列??
qldsrx 2010-01-09
  • 打赏
  • 举报
回复
IServer就是一个接口定义,单独创建了一个只包含接口的项目,同时给服务端和客户端引用。虽然它支持通过引用服务的方式添加,但是除非是服务端已经写好并无法获知接口的情况,一般不用那个方法添加客户端引用,因为它那种方法很麻烦,还得服务端开启一下,然后客户端才能更新,更新后的效果说不定还会和接口不一致,不好控制。
dqy007 2010-01-09
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 qldsrx 的回复:]
我是这么写的:
C# codepublicstaticclass DataManager
{#region 私有变量staticstring uri="localhost:12345";static IServer channel;#endregion#region 属性publicstaticstring URI
{get {return uri; }set
{
uri= value;
channel=null;
}
}publicstatic IServer Channel
{get
{if (channel==null)
{
ICollection<BindingElement> bindingElements=new List<BindingElement>();
TcpTransportBindingElement tcpTransport=new TcpTransportBindingElement() { TransferMode= TransferMode.Streamed, MaxReceivedMessageSize=2147483647 }; ;
GZipMessageEncodingBindingElement compBindingElement=new GZipMessageEncodingBindingElement(new BinaryMessageEncodingBindingElement());
bindingElements.Add(compBindingElement);
bindingElements.Add(tcpTransport);
CustomBinding binding=new CustomBinding(bindingElements);
binding.Name="tcpTransport";
EndpointAddress address=new EndpointAddress(new Uri("net.tcp://"+ uri+"/Server/"));
ChannelFactory<IServer> channelFactory=new ChannelFactory<IServer>(binding, address);
channelFactory.Endpoint.Behaviors.Add(new ContextHeaderBehavior());
channel= channelFactory.CreateChannel();
}return channel;
}
}#endregion
}
这只是一部分代码,使用时直接访问Channel属性,为null就自动初始化,除非外部改变URI,否则Channel只要初始化一次,以后不论网络状况如何,是否出现连接上的错误,都可以一直使用那个Channel。
[/Quote]
你这里的IServer是不是从WCF通过引用服务创建的名称???
qldsrx 2010-01-09
  • 打赏
  • 举报
回复
我是这么写的:

public static class DataManager
{
#region 私有变量
static string uri = "localhost:12345";
static IServer channel;
#endregion

#region 属性
public static string URI
{
get { return uri; }
set
{
uri = value;
channel = null;
}
}

public static IServer Channel
{
get
{
if (channel == null)
{
ICollection<BindingElement> bindingElements = new List<BindingElement>();
TcpTransportBindingElement tcpTransport = new TcpTransportBindingElement() { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 2147483647 }; ;
GZipMessageEncodingBindingElement compBindingElement = new GZipMessageEncodingBindingElement(new BinaryMessageEncodingBindingElement());
bindingElements.Add(compBindingElement);
bindingElements.Add(tcpTransport);
CustomBinding binding = new CustomBinding(bindingElements);
binding.Name = "tcpTransport";
EndpointAddress address = new EndpointAddress(new Uri("net.tcp://" + uri + "/Server/"));
ChannelFactory<IServer> channelFactory = new ChannelFactory<IServer>(binding, address);
channelFactory.Endpoint.Behaviors.Add(new ContextHeaderBehavior());
channel = channelFactory.CreateChannel();
}
return channel;
}
}
#endregion
}

这只是一部分代码,使用时直接访问Channel属性,为null就自动初始化,除非外部改变URI,否则Channel只要初始化一次,以后不论网络状况如何,是否出现连接上的错误,都可以一直使用那个Channel。
talen_lu 2010-01-07
  • 打赏
  • 举报
回复
用remoting没出现个这种问题。
qldsrx 2010-01-07
  • 打赏
  • 举报
回复
附带说一下,我用的是流传输模式。
qldsrx 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 dqy007 的回复:]
我的服务器过程契约是这样的[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)],这种有没有问题
[/Quote]
你添加InstanceContextMode = InstanceContextMode.PerCall后,ConcurrencyMode = ConcurrencyMode.Multiple是没有意义的,PerCall模式不需要设置ConcurrencyMode,肯定是每个访问独立的。
[Quote=引用 21 楼 dqy007 的回复:]
不是不知道怎么处理出错,意思是再次用到这个实例之前要判断是否有效,但是这个实例没有属性能提示它失效了还是在连接状态,
[/Quote]
PerCall模式下,没有连接与断开的概念,如果你客户端创建了与服务器端的一个连接实例,就全局保存它吧,因为那个实例永远不可能失效,即使客户端将网线拔掉,检查它的连接状态仍旧是已经连着的状态,不会显示为断开状态,除非自己手动去关闭连接。
至于检测连接状态,找到你创建的ChannelFactory<IServer>对象,ChannelFactory<IServer>.State属性就是连接状态。
cczdp 2010-01-07
  • 打赏
  • 举报
回复
1. 你的程序设计首先有问题,当你加载所有项的时候,不要触发改变事件。解决方案是设置一个开关变量,当加载的时候变量为false,加载完设置为true;在下拉框改变事件中判断是true才处理。
2. wcf不会卡,我们做压力测试2000个用户并发访问都没有问题,何况你一个用户,应该是你的调用wcf的代码部分有问题,但是没有代码,不好说什么问题。
lsd123 2010-01-07
  • 打赏
  • 举报
回复
.
dqy007 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 icbc_ljt 的回复:]
引用 19 楼 dqy007 的回复:
引用 16 楼 vrhero 的回复:
那就要靠你去平衡了...比如自己构造一个pool建立空闲回收机制和连接状态检测等...

如果是IIS承载的WCF就是HTTP协议,不存在“时时要跟服务器连接”,只是在客户端维持一个通道...

看似麻烦,代价却远小于频繁开闭...

我是软件的,用net.tcp的, 搞个全局打开通道方法,我试过的,的确不会卡,但是只要网络断一回,这个通道就失效,再用时就出错,但是又没有找到判断这个通道失效的属性,所以又很麻烦



加try{}
  catch{}
处理吧
[/Quote]

不是不知道怎么处理出错,意思是再次用到这个实例之前要判断是否有效,但是这个实例没有属性能提示它失效了还是在连接状态,
icbc_ljt 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 dqy007 的回复:]
引用 16 楼 vrhero 的回复:
那就要靠你去平衡了...比如自己构造一个pool建立空闲回收机制和连接状态检测等...

如果是IIS承载的WCF就是HTTP协议,不存在“时时要跟服务器连接”,只是在客户端维持一个通道...

看似麻烦,代价却远小于频繁开闭...

我是软件的,用net.tcp的, 搞个全局打开通道方法,我试过的,的确不会卡,但是只要网络断一回,这个通道就失效,再用时就出错,但是又没有找到判断这个通道失效的属性,所以又很麻烦
[/Quote]


加try{}
catch{}
处理吧
dqy007 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 vrhero 的回复:]
那就要靠你去平衡了...比如自己构造一个pool建立空闲回收机制和连接状态检测等...

如果是IIS承载的WCF就是HTTP协议,不存在“时时要跟服务器连接”,只是在客户端维持一个通道...

看似麻烦,代价却远小于频繁开闭...
[/Quote]
我是软件的,用net.tcp的, 搞个全局打开通道方法,我试过的,的确不会卡,但是只要网络断一回,这个通道就失效,再用时就出错,但是又没有找到判断这个通道失效的属性,所以又很麻烦
icbc_ljt 2010-01-07
  • 打赏
  • 举报
回复
可不可以在客户端设置多几个断点看看到底在那里浪费时间,再作下一步打算?
还有,你说连续打开,干脆第一个通道关闭后先sleep两秒,再运行,看是不是运行后比两秒还要长很多
vrhero 2010-01-07
  • 打赏
  • 举报
回复
另外不是一个“变量”那么简单...你似乎还停留在Delphi或VB6的开发模式中,去看看OOADP的知识,WCF不止是一种通讯模式,也是一种开放式设计的理念...
vrhero 2010-01-07
  • 打赏
  • 举报
回复
那就要靠你去平衡了...比如自己构造一个pool建立空闲回收机制和连接状态检测等...

如果是IIS承载的WCF就是HTTP协议,不存在“时时要跟服务器连接”,只是在客户端维持一个通道...

看似麻烦,代价却远小于频繁开闭...
dqy007 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 qldsrx 的回复:]
引用 7 楼 dqy007 的回复:
    我刚才说,就是本地数据也会卡,这个卡不是数据的问题,是频繁打开通道的问题,只是有的情况下不频繁打开通道不行呀

不好意思,没看到你这里的回复。上面也说了,肯定不是通道频繁打开的问题,你还是检查下程序设计上的问题吧。
[/Quote]
我的服务器过程契约是这样的[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)],这种有没有问题
dqy007 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 vrhero 的回复:]
引用 10 楼 dqy007 的回复:
    这二次打开,是夸模块的,A模块关不关,跟B模块有什么关系

跨模块又怎样?跨程序集都能实现...想一下数据库连接是怎么开闭的,把WCF客户端做为一个独立的provider设计,不用去管A模块还是B模块...
[/Quote]
你的意思是一个程序做一个全局通道变量,这样就是时时要跟服务器连接了,不说对服务器有负担,假如网络断一回,你这个变量就出问题,,,怎么解决
vrhero 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 dqy007 的回复:]
    这二次打开,是夸模块的,A模块关不关,跟B模块有什么关系
[/Quote]
跨模块又怎样?跨程序集都能实现...想一下数据库连接是怎么开闭的,把WCF客户端做为一个独立的provider设计,不用去管A模块还是B模块...
加载更多回复(12)

111,120

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧