C# 在多个并发异步调用的客户端中出现随机TimeoutException

C# 在多个并发异步调用的客户端中出现随机TimeoutException,c#,wcf,soap,asynchronous,C#,Wcf,Soap,Asynchronous,我有一个TimeoutException问题,我正在使用C#4.0(短期内无法升级到4.5)和WCF。请注意,我不控制服务器,也看不到所使用的代码和/或技术。问题发生在由不同人员制造的不同服务器上 我将尽可能多的请求发送到多个服务器(比如10个),每个服务器在任何时候发送一个请求。它们从每秒2到30个请求。在30秒到5分钟之间,我将得到一些TimeoutException: exception {"The HTTP request to 'http://xx.xx.xx.xx/service

我有一个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 ...
例外情况是:

[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代替信号量,结果相同)

我试过了

ServicePointManager.DefaultConnectionLimit = 200;
ServicePointManager.MaxServicePointIdleTime = 2000;
正如一些帖子所暗示的,没有成功

即使我设置了非常高的打开、发送、接收和关闭超时,它也会执行相同的异常。WCF似乎在发送请求时“卡住了”。服务器继续正确响应其他请求

你知道吗

而且,如果我这样做(在回调中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);
    }
}

经过更多的测试,我发现如果begin/end机制没有在同一个线程池上执行,它将随机执行此行为

在第一种情况下,“AsyncTest”是在具有ThreadStart和thread的新线程中生成的。在第二种情况下,只在专用线程上调用第一个“begin”,因为问题是随机发生的,所以在第一个请求时发生异常的可能性很小。另一个“开始”是在.net线程池上创建的

通过在第一种情况下使用Task.Factory.StartNew(()=>AsyncTest()),问题就消失了

在我的实际项目中,我仍然使用CCR(和CCR线程池)来完成所有工作,直到我必须调用begin/end。。我将使用.net线程池,现在一切正常


有人能更好地解释为什么WCF不喜欢在另一个线程池上被调用吗?

经过更多的测试,我发现如果begin/end机制没有在同一个线程池上执行,它将随机执行此行为

在第一种情况下,“AsyncTest”是在具有ThreadStart和thread的新线程中生成的。在第二种情况下,只在专用线程上调用第一个“begin”,因为问题是随机发生的,所以在第一个请求时发生异常的可能性很小。另一个“开始”是在.net线程池上创建的

通过在第一种情况下使用Task.Factory.StartNew(()=>AsyncTest()),问题就消失了

在我的实际项目中,我仍然使用CCR(和CCR线程池)来完成所有工作,直到我必须调用begin/end。。我将使用.net线程池,现在一切正常

有人能更好地解释为什么WCF不喜欢在另一个线程池上调用吗?

注意到,谢谢:)这可能是WCF中的一个bug吗?它发生在我们所有的机器上,并尝试了许多其他来源的“修复”,但都没有成功。我可以在一分钟内复制它。ChannelFactory的结果也是一样,每次调用一个通道。注意,谢谢:)这可能是WCF中的错误吗?它发生在我们所有的机器上,并尝试了许多其他来源的“修复”,但都没有成功。我可以在一分钟内复制它。对于ChannelFactory,每次调用一个通道的结果也是一样的。
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);
    }
}