我有一个TimeoutException问题,我正在使用C#4.0(不能很快升级到4.5)和WCF。请注意,我不控制服务器,也看不到使用的代码和/或技术。问题发生在不同人制作的不同服务器上。
我尽可能多地向许多服务器发送请求(假设为10),每个服务器随时发送一个。它们每秒发出2到30个请求。在30秒到5分钟之间,我会得到一些TimeoutException:
exception {"The HTTP request to 'http://xx.xx.xx.xx/service/test_service' has exceeded the allotted timeout of 00:02:10. The time allotted to this operation may have been a portion of a longer timeout."} System.Exception {System.TimeoutException}.
Stack Trace :
Server stack trace:
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at Device.EndTest(IAsyncResult result)
at DeviceClient.EndTest(IAsyncResult result) in ...
at TestAsync(IAsyncResult ar) in ...
InnerException是:
[System.Net.WebException] {"The request was aborted: The request was canceled."} System.Net.WebException
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
Wireshark告诉我,我甚至没有打开连接(没有SYN)。所以这应该是一个客户问题。我在TCPView中有许多TIME_WAIT连接
使用同步通话正在运行,但无法实现。
请注意,在以下代码示例中,每个服务器有一个方法调用。 (在我的例子中,10个并发的TestAsync)
(在实际项目中,我们使用CCR而不是Semaphore,结果相同)
private void AsyncTest()
{
//GetServiceObject Will add custom bindings and more..
Client client = ClientBuilder.GetServiceObject();
while (true)
{
Semaphore semaphore = new Semaphore(0,1);
client.BeginTest(BeginTestCallback, new AsyncState
{
Client = client,
Semaphore = semaphore
});
semaphore.WaitOne();
}
}
private void BeginTestCallback(IAsyncResult asyncResult)
{
try
{
AsyncState state = asyncResult.AsyncState as AsyncState;
Client client = state.Client;
Semaphore semaphore = state.Semaphore;
Client.EndTest(asyncResult);
semaphore.Release();
}
catch (Exception e)
{
//Will catch the exception here because of Client.EndTest(asyncResult)
Debug.Assert(false, e.Message);
}
}
我试过
ServicePointManager.DefaultConnectionLimit = 200;
ServicePointManager.MaxServicePointIdleTime = 2000;
正如一些帖子所说,没有成功。
即使我设置了高度打开,发送,接收和关闭超时,它也会执行相同的异常。 WCF似乎在发送请求时“卡住”了。服务器继续正确响应其他请求。
有什么想法吗?
另外,如果我这样做(Callback中的BeginTest而不是while(true)),它将永远不会发生异常吗?!?!
private void AsyncTest()
{
//GetServiceObject Will add custom bindings and more..
Client client = ClientBuilder.GetServiceObject();
try
{
client.BeginTest(BeginTestCallback, new AsyncState
{
Client = client
});
}
catch (Exception e)
{
Debug.Assert(false, e.Message);
}
}
private void BeginTestCallback(IAsyncResult asyncResult)
{
try
{
AsyncState state = asyncResult.AsyncState as AsyncState;
state.Client.EndTest(asyncResult);
state.Client.BeginTest(BeginTestCallback, state);
}
catch (Exception e)
{
//No Exception here
Debug.Assert(false, e.Message);
}
}
答案 0 :(得分:1)
经过更多测试后,我发现如果开始/结束机制没有在同一个线程池上执行,它会随机执行此行为。
在第一种情况下,使用ThreadStart和Thread在新线程中生成“AsyncTest”。在第二种情况下,在专用线程上只调用第一个“开始”,并且由于问题是随机发生的,因此在第一个请求上发生异常的可能性很小。另一个“开始”是在.net ThreadPool上创建的。
在第一种情况下使用Task.Factory.StartNew(()=> AsyncTest()),问题就消失了。
在我的真实项目中,我仍然使用CCR(和CCR线程池)来做所有事情,直到我必须调用开始/结束..我将使用.net线程池,现在一切正常。
任何人都能更好地解释为什么WCF不喜欢在另一个线程池上调用?