25个并发异步WCF调用使用任务进行编排

时间:2013-05-07 07:50:14

标签: wcf c#-4.0 task

我有一个应用程序(.NET 4.0),它在启动时加载管理数据。我必须进行25次并发异步WCF调用,其中一些是快速(40ms),有些则需要更长时间才能执行,最多882 ms。我计划在本地存储数据,但是对于第一次应用程序启动,它需要尽快完成。

应该注意的是,代理服务器位于一个面向.NET 3.5的库中,并且在Jeffrey Richter的Async Enumerator的帮助下,内部使用BeginXxx和EndXxx方法模式封装成异步方法。

将在启动调用之前打开将使用的每个客户端代理的WCF通道工厂。

此时,我正在使用Task.Factory.StartNew执行一个启动每个异步调用的操作。经验如下:

  1. 所有BeginXXX电话都已发送。
  2. 该程序似乎在我的代码之外工作至少10秒。
  3. 最后发送所有EndXXX调用以检索结果。
  4. 我想知道为什么会出现这种延迟。我的计算机有4个核心,如果并发呼叫数量限制为4个,则没有任何延迟,只要我再添加一个呼叫,就会遇到延迟。

    任何帮助表示感谢。

    编辑1 :使用的绑定是netTcpBinding。

    服务器配置如下:

         <netTcpBinding>
            <binding transactionFlow="true" listenBacklog="500" maxReceivedMessageSize="400000"
        portSharingEnabled="false">
             <readerQuotas maxDepth="200" />
             <reliableSession enabled="false" />
             <security mode="None">
                <transport clientCredentialType="None" protectionLevel="None" />
                <message clientCredentialType="None" />
             </security>
            </binding>
         </netTcpBinding>
    
    <service name="AdminService">
            <endpoint address="" binding="netTcpBinding" bindingConfiguration=""
         contract="IAdmin">
             <identity>
                <dns value="localhost" />
             </identity>
            </endpoint>
            <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
         contract="IMetadataExchange" />
         </service>
    

    EDIT 2 :以下是4 Core机器上WCF 4.5运行时设置的默认限制值。

    ListenBacklog is [500]
    MaxConnections is [48]
    MaxConcurrentCalls is [64]
    MaxConcurrentInstances is [2147483647]
    MaxConcurrentSessions is [400]
    

    编辑3 :以下是使用J.Richter的AsyncEnumerator的代码:

           private IEnumerator<int> DoWorkGetXXXX(AsyncEnumerator<MyResult> ae)
            {
                ae.ThrowOnMissingDiscardGroup(true);
    
                IClientChannel proxy = (IClientChannel)CreateChannel(_bindingName);
    
                bool success = false;
                try
                {
                    proxy.Open();
                    // The call to BeginXXX goes here
                    ((IAcaccount)proxy).BeginGetXXX(..., ae.EndVoid(0, DiscardGetXXX), proxy);
                    //
                    yield return 1;
    
                    if (ae.IsCanceled())
                    {
                        goto Complete;
                    }
                    // Iterator was not canceled, process should continue.
    
                    // The call to EndXXX goes here
                    IAsyncResult ar = ae.DequeueAsyncResult();
                    try
                    {
                        ae.Result = ((IAcaccount)ar.AsyncState).EndGetXXX(ar);
                        proxy.Close();
                        success = true;
                    }
                    // In the mean time, we catch and rethrow :)
                    // If this exception occurs, we should retry a call to the service
                    catch (FaultException<AppFabricCachingException> retry)
                    {
                    }
                    // fatal Exception in data service, administrator action required...
                    catch (FaultException<EFExecutionException> fatal)
                    {
                    }
                    catch (FaultException<EFUpdateException> fatal)
                    {
                    }
                    catch (FaultException<EFNoRowException> nr)
                    {
                    }
                    catch (FaultException fe)
                    {
                    }
                    catch (ServiceActivationException sae)
                    {
                    }
                    catch (CommunicationException ce)
                    {
                    }
                    //
    
                }
                finally
                {
                    // If an error occurred, abort the proxy.
                    if (!success)
                    {
                        proxy.Abort();
                    }
                }
    
    
        // End of operations.
            Complete:
                proxy = null;
            }
    

1 个答案:

答案 0 :(得分:0)

您可以尝试使用serviceThrottling的值,以及maxItemsInObjectGraph,maxBufferSize,MaxBufferPoolSize(我将它们设置为int.MaxValue)。