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

Oli*_*ROT 5 wcf task c#-4.0

我有一个应用程序(.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,则根本没有延迟,只要我再添加一个呼叫,就会遇到延迟.

任何帮助赞赏.

编辑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>
Run Code Online (Sandbox Code Playgroud)

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

ListenBacklog is [500]
MaxConnections is [48]
MaxConcurrentCalls is [64]
MaxConcurrentInstances is [2147483647]
MaxConcurrentSessions is [400]
Run Code Online (Sandbox Code Playgroud)

编辑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;
        }
Run Code Online (Sandbox Code Playgroud)

ath*_*ska 0

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