我有一个WCF服务,有时必须返回一个错误。出于某种原因,对我的服务的调用开始超时,出现以下错误: “请求通道在00:00:59.8906201之后等待回复时超时。增加传递给Request的调用的超时值或增加Binding上的SendTimeout值。分配给此操作的时间可能是一部分更长的超时。“
检查问题后,出现了一种模式:当服务10次返回故障时,超时开始。所以我创建了一个由以下实现的测试服务:
public string GetData(int value)
{
throw new FaultException("A testerror occured");
}
还有一个测试客户:
protected void RunTestGetData()
{
using (TestServiceReference.Service1Client client
= new WSPerformanceTester.TestServiceReference.Service1Client())
{
try
{
client.GetData(1);
client.Close();
outputWriter.WriteLine(string.Format("Call run in thread {0}: GetData()", Thread.CurrentThread.ManagedThreadId));
outputWriter.Flush();
}
catch (Exception e)
{
client.Abort();
client.Close();
outputWriter.WriteLine(string.Format("Error occured in thread {0}: GetData(): {1}", Thread.CurrentThread.ManagedThreadId, e.Message));
outputWriter.Flush();
}
}
}
只有在服务返回FaultException时才会发生这种情况。如果我抛出正常异常,服务可以在第10次调用后继续运行。显然,我想很好地包装我的异常,所以抛出正常异常并不是一个真正的选择。
为什么我会遇到这些超时异常?提前感谢您的帮助..
答案 0 :(得分:3)
我没有足够的评论意见,所以新回复......
自托管服务最多只允许10个并发连接 - 无论传输。如果你在IIS / WAS中运行WCF服务,你不必担心这个问题(除非你在最大并发连接数为10的XP / Vista上)。
此方案中的故障异常与常规异常之间的差异可以说明您所看到的结果。
请记住,常规的未处理异常会导致频道出错。这样做我认为这会打开一个可用的连接。当你返回一个故障时,它会“自动地对通道进行故障,因为它允许你对连接做一些事情并在你的末端处理故障,因为它可能是”预期的“故障,而未处理的异常则不会。
即使您返回故障,仍然需要中止()连接。此外,还有非托管资源,所以一定要在客户端/代理的呼叫者上实现IDisposable。
答案 1 :(得分:2)
我认为这可能是因为WCF服务的默认行为是10个并发会话。 在FaultExceptions发生后,您是否保持连接打开?您可以尝试在BehaviorConfiguration(ServiceThrottling> MaxConcurrentSessions)中更改此值,并查看是否更改了任何内容。 我建议您使用Microsof服务配置编辑器检查默认情况下设置的其他值。 (MSDN)
希望这会有所帮助...
答案 2 :(得分:2)
我遇到了同样的问题。仔细观察后发现,在我完成对Web服务的调用之后,我没有关闭Web服务客户端。一旦我这样做,即使在10次方法调用webservice之后它也没有失败。请参阅下面的示例。
WebServiceClient svcClient = new WebServiceClient();
string returnValue = svcClient.GetDocumentName(fileId);
svcClient.Close();
正确的模式:
using(WebServiceClient svcClient = new WebServiceClient())
{
return svcClient.GetDocumentName(fileId);
}
ClientBase
实施IDisposable
,在Close()
方法中调用Dispose
。
答案 3 :(得分:1)
我可能在这里错了,但我认为它与托管WCF服务有关。
因为它可能无法及时响应请求。
例如,Windows XP上的IIS可以回复5(并且我现在不太确定)同时请求。如果发出更多请求,它将进入队列。我相信它可能会丢失请求,并且这样做,而不是处理它们,因为你的测试实际上什么都不做,只是抛出异常。
答案 4 :(得分:1)
显然,客户端代码应如下所示:
protected void RunTestGetData()
{
TestServiceReference.Service1Client client
= new WSPerformanceTester.TestServiceReference.Service1Client()
try
{
client.GetData(1);
}
catch (FaultException e)
{
//Handle fault
}
try
{
if (client.State != System.ServiceModel.CommunicationState.Faulted)
{
client.Close();
}
}
catch(Exception e)
{
outputWriter.WriteLine("Error occured in Client.Close()");
outputWriter.Flush();
client.Abort();
}
}
调用client.Abort()应始终是最后的手段。
答案 5 :(得分:0)