5

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

应该注意的是,代理位于针对 .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>

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

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;
        }
4

1 回答 1

0

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

于 2013-05-31T06:46:29.403 回答