代码之家  ›  专栏  ›  技术社区  ›  Saurabh Kumar

我陷入僵局了吗?为什么?

  •  2
  • Saurabh Kumar  · 技术社区  · 15 年前

    我有一个Silverlight 3应用程序需要调用WCF服务。WCF服务反过来调用ASMX Web服务。当WCF服务调用完成时,需要更新Silverlight UI。

    正在异步中调用WCF。

    问题是Silverlight应用程序需要数百次调用wcf方法(稍后在内部调用asmx)。我理解,因为它是异步的,所以将产生数百个线程,所以我在检查中进行了编码,以确保调用wcf函数的时间不超过x次。只有当一个呼叫完成时,我才能再添加一个呼叫。我希望这将检查线程总数。X值的理想值是多少?我是一个简单的XP机器,有双核CPU和4GB内存。

    当WCF调用完成时,我需要在Silverlight UI上显示进度条。

    这对于较小的调用数很好,但是当我需要进行大约10000个调用时,经过一段时间后,我会在Silverlight的wcfCompleted方法中获得超时。我觉得我可能会陷入僵局?

    我的wcf配置为多个并发。

    每次一个WCF调用完成时,它都会更新用户界面…这会导致僵局吗?

    有什么想法吗?我困在这里,迷路了。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Mark Ransom    15 年前

    死锁只在一个线程分配一个资源并等待另一个资源时产生,而另一个线程分配第二个资源并等待第一个资源时产生。谁也不能继续。

    问题是,当多个线程调用Windows UI时,没有一个线程知道Windows试图使用的内部资源。不可能预测结果会是什么;僵局是一种可能性。

        2
  •  0
  •   Steve Severance    15 年前

    所以成百上千的线不会被旋转,除非你这样做。异步调用的要点是,在操作完成并发布到完成端口之前,调用是发出的,没有任何东西存在(因为不会发生任何事情)。这假定您正在使用回调。如果在iasyncresult上调用endxxx,则线程将阻塞,直到操作完成。

    现在可能会发生一些事情。首先,如果您有一个复杂的服务后端,那么您的服务中可能有一个死锁。不过,第二个,可能更可能是您的WCF服务配置需要调整。WCF调优是一种黑色艺术,一旦你理解了,你通常发誓你将不再使用WCF。

    在您的客户机上同时允许多少个出站连接,反之,在您的服务上允许多少个入站连接?使用 WCF tracing 在客户机和服务器上通常都需要解决这些类型的问题。我建议你从那里开始,因为我会让你了解你需要了解的细节,看看到底发生了什么。

        3
  •  0
  •   Community Mohan Dere    9 年前

    在这种情况下,我怀疑您是否遇到了线程死锁。WPF和我也相信Silverlight使用线程调度程序将消息从工作线程发送到UI。这就是为什么这样的用户界面如此响应的原因之一。更可能的情况是,您正在重载WCF端点堆栈、其缓冲区或ASP.NET管道堆栈和/或缓冲区。在处理网络连接时,对于创建大量连接的速度和频率有一些限制。如果您在彼此几分钟内创建了10000个连接,则完全有可能超出TCP堆栈。当一个套接字被关闭时,它不会立即被重用,并进入一个最终的等待状态大约4分钟。如果您在4分钟内触发了几批10000个连接,您将消耗所有可用的套接字,从而导致WCF(以及任何其他具有保留端口的Windows应用程序)无法通信。我不能肯定你会遇到这种情况(你 真正地 需要使用 许多 但我在这里详细回答了另一个关于如何增加Windows TCP堆栈的默认阈值的问题:

    WCF: System.Net.SocketException - Only one usage of each socket address (protocol/network address/port) is normally permitted

    如果您真的希望深入到问题的底部,我建议您启用WCF跟踪日志记录。WCF跟踪日志捕获了大量的信息,并提供了有关所处理的每个连接和消息的极其详细的信息。启用后,您应该能够识别问题,除非它在到达WCF之前发生在ASP.NET管道或HTTP.sys中。我建议阅读以下文章:

        4
  •  0
  •   Saurabh Kumar    15 年前

    后来我似乎通过以下方式解决了这个问题: 1)将asmx服务转换为wcf 2)WCF超时从1分钟增加到5分钟 3)我现在使用的计时器不是每次完成回调时更新UI进度条,而是每30秒更新一次UI。