我有一个.NET 4.5 WCF客户端应用程序,它使用async / await模式来进行大量调用。我的开发机器是带有8GB RAM的双进程(在亚马逊AWS上将生产5个CPU和8GB RAM)。我的代码调用的远程WCF服务在我需要的Web方法上使用out和ref参数。我的代码每次都实例化一个代理客户端,将任何结果写入公共ConcurrentDictionary,然后返回null。
我跑了Perfmon,看着系统上的线程计数,它在28-30之间。我的客户端需要几个小时才能完成所做的调用。是的,几小时。远程服务由一家大公司支持,他们有许多服务器来接收我的WCF呼叫,因此我可以向他们拨打的电话越多越好。
我认为事情实际上仍然是同步发生的,即使使用“async”进行WCF调用的方法也是如此,因为代理方法不能“等待”。真的吗?
我的代码如下所示:
async private void CallMe()
{
Console.WriteLine( DateTime.Now );
var workTasks = this.AnotherConcurrentDict.Select( oneB => GetData( etcetcetc ).Cast<Task>().ToList();
await Task.WhenAll( workTasks );
}
private async Task<WorkingBits> GetData(etcetcetc)
{
var commClient = new RemoteClient();
var cpResponse = new GetPackage();
var responseInfo = commClient.GetData( name, password , ref (cpResponse.aproperty), filterid , out cpResponse.Identifiers);
foreach (var onething in cpResponse.Identifiers)
{
// add to the ConcurrentDictionary
}
return null; // I already wrote to the ConcurrentDictionary so no need to return anything
由于WCF调用具有ref和out参数,因此无法响应responseInfo。
我认为加快这一步的方法不是在这个方法中放入async / await,而是创建一个包装器方法,我可以让事情等待/异步,但我不是那种最聪明/最安全的方式解决它。
什么是获得更多服务出站调用的智能方法(扩展IO完成线程池,将调用设置为在后台运行,以便Task.WhenAll可以更快地完成)?
感谢所有想法/样本/指针。我在某个地方遇到了瓶颈。
答案 0 :(得分:3)
1)确保你真的是异步调用它,而不是仅仅阻止调用。代码示例在这里会有所帮助。
2)您可能需要这样做:
ServicePointManager.DefaultConnectionLimit = 100;
默认情况下,它只允许同时连接到同一台服务器 3)确保在呼叫完成后丢弃代理对象,这样就不会占用资源。
如果您正在异步执行操作,则线程池大小不应成为瓶颈。为了更好地了解您遇到的问题类型,您可以使用Interlocked.Increment
和Interlocked.Decrement
来跟踪待处理呼叫的数量,并查看它是否在某个地方受到限制。
您也可以通过调用一个非常简单的方法来替换您的真实呼叫,该方法您知道不会有任何瓶颈,以查看问题是在客户端还是服务器中。