【问题标题】:TryReceiveRequest gets called infinite timesTryReceiveRequest 被无限次调用
【发布时间】:2010-11-18 14:58:40
【问题描述】:

我已经构建了一个自定义绑定,以便能够从其他来源接收 HTTP 消息。但是,它还不是没有错误的。

我观察到,一旦处理了第一个请求,我的服务就会将 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在关闭回复上下文后不关闭通道,虽然在消费后保持通道打开是没有用的?

【问题讨论】:

  • 我可以通过修改通道的WaitForRequest方法来减少CPU负载。因此,TryReceiveRequest 调用正确完成。但是,ServiceModel 不断向 TryReceiveRequest 发送垃圾邮件。如果在一段时间内没有任何内容可阅读,是否有可能关闭连接?
  • 手动调用 close 并没有阻止 ServiceModel 调用 BeginTryReceiveRequest。停止该行为的唯一方法是手动调用 Abort() ,这似乎不是解决我的问题的正确方法。

标签: wcf wcf-binding extensibility transport


【解决方案1】:

所以,也许有人仍然需要解决这个问题。在 BeginTryReceiveRequestEndTryReceiveRequest 检查通道的 State 属性。

.....

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

【讨论】:

  • 除了返回 null 之外,您还可以抛出 CommunicationObjectAbortedException 或 CommunicationObjectFaultedException 异常
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多