2009-08-11 54 views
0

我已经构建了一个自定义绑定,可以从其他源接收HTTP消息。但是,它还没有缺陷。TryReceiveRequest被调用无限次

我发现我的服务一旦处理第一个请求就将CPU使用率提高到100%,并且服务越来越慢,请求进来越多。插入日志记录后可以看到此行为的原因命令转换为绑定的每个单一功能。

直到第一个请求获取之前,一切工作正常:

ChannelListener: OnBeginAcceptChannel 
ChannelListener: OnAcceptChannel 

然后,第一条消息的处理完成:

Channel: static constructor 
Channel: constructor 
ChannelListener: OnEndAcceptChannel (completes) 
ChannelListener: Uri get 
ChannelListener: OnBeginAcceptChannel 
ChannelListener: OnAcceptChannel 
Channel: OnOpen 
Channel: BeginTryReceiveRequest 
Channel: TryReceiveRequest 
Channel: WaitForRequest 
Channel: ReceiveRequest 
Context: constructor 
Channel: EndTryReceiveRequest (completes) 
Context: RequestMessage get 
`Channel: BeginTryReceiveRequest` 
Context: Reply noTimeout 
Context: Reply 
Context: Close noTimeout 
`Channel: TryReceiveRequest` 
`Channel: WaitForRequest` 
`Channel: ReceiveRequest (hangs)` 
`Channel: EndTryReceiveRequest (doesn't complete since receive hangs)` 
`Channel: BeginTryReceiveRequest` 
`and so on...` 

通道实现IReplyChannel接口,所以它应该只有可能获得请求,回复并关闭频道。 而不是仅仅关闭频道,ServiceModel会在已使用的频道上发送TryReceiveRequest垃圾信息,无论过去是否使用过频道。

有什么方法可以解决这个问题吗?为什么ServiceModel在关闭回复上下文后关闭了通道,尽管在通道消耗之后保持通道打开没有用处?

+0

我可以通过修改信道的方法WaitForRequest降低CPU的负荷。因此,TryReceiveRequest调用正确完成。但是,ServiceModel不断发送垃圾邮件TryReceiveRequest。如果在某段时间内没有任何内容需要阅读,是否有可能关闭连接? – Etan 2009-08-12 08:17:30

+0

手动调用close并不会阻止ServiceModel调用BeginTryReceiveRequest。只有停止行为的方法是手动调用Abort(),这似乎不是我的问题的正确解决方案。 – Etan 2009-08-12 12:17:46

回答

0

所以,也许有人仍然需要解决这个问题。检查状态渠道属性BeginTryReceiveRequestEndTryReceiveRequest

.....

public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) 
     { 
      if (State == CommunicationState.Closed) 
      { 
       return null; 
      } 
      return new TryReceiveRequestAsyncResult(timeout, this, callback, state); 
     } 

.....

public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context) 
      { 
       if (State == CommunicationState.Closed) 
       { 
        context = null; 
        return false; 
       } 
       return TryReceiveRequestAsyncResult.End(result, out context, this); 
      }