【发布时间】:2012-08-31 14:22:24
【问题描述】:
我正在开发 WCF 客户端/服务器应用程序,客户端通过将调用包装在 Task.Factory.StartNew 中并在 WCF 调用返回时使用延续调用用户提供的委托来异步调用服务器。服务器操作在向客户端返回响应之前执行(除其他外)一些串行 I/O。该服务还利用 BlockingCollection 将这些请求排入队列,确保它们一次执行一个,以避免串行端口争用。就目前而言,应用程序运行良好,即使客户端快速连续向服务器发出大量请求。
现在,应用程序还可以配置为以“直接”模式运行,其中客户端直接引用服务器端程序集(出于性能原因,如果客户端和服务器位于同一台 PC 上)。在这种情况下,客户端使用服务类的实例(而不是 ChannelFactory 创建的代理)并直接调用其操作方法,使用相同的异步 Task.Factory.StartNew 帮助器。
在这种“直接”模式下,我发现服务器端执行似乎运行缓慢(它错过了串行端口数据),就好像它以某种方式被中断了一样。我可以通过将客户端任务更改为使用TaskCreationOptions.LongRunning 来“修复”它。不幸的是,这会在“WCF 模式”下破坏应用程序,这似乎会遇到同样的缓慢问题。
现在,我可以简单地包含 TaskCreationOptions(或不包含),具体取决于应用程序使用的“模式”,但我想首先了解为什么会发生这种情况。有什么想法吗?
编辑:
我注意到应用程序启动期间的问题,当客户端在for 循环中一个接一个地向服务器发送十几个请求时。在此之后,客户端每半秒轮询一次服务器 - 这不受问题的影响,其他两个同时运行客户端和服务器端的线程计时器也不受此影响(其中一个每 65 毫秒触发一次!)。我看到一篇文章说线程池将创建新线程,直到达到最小线程数,之后它将创建的线程数限制为每 500 毫秒一个。这与我的问题的症状相匹配,因为我看到大约每半秒出现一次缓慢。
我将重构我的客户端代码以避免快速连续多次访问服务器,这是一种耻辱。我真的很想一个接一个地触发所有这些请求,然后在服务器处理完回调委托后处理结果。但是有了这个线程池“功能”,我似乎无法做到这一点。
【问题讨论】:
-
首先想到的疯狂猜测是,直接端的代理类正在幕后做一些事情——目前还不知道——直接实例版本不是。这就是我开始寻找的地方,至少......
-
您可以在您的客户端/服务器之间共享某个对象的实例吗?在 WCF 模式下,您不会共享实例,在直接模式下,您可能会共享实例,您可能对此有疑问?
-
@jasper 链接是通过“外观”项目建立的——客户端直接引用此项目,但没有直接引用服务器端程序集。
-
您的更新还解释了 LongRunning 解决它的原因,因为它不再使用线程池
标签: c# .net multithreading wcf task-parallel-library