0

I have built a custom binding for being able to receive HTTP messages from an additional source. However, it is not bug-free yet.

I've observed that my service pushes CPU usage up to 100 % as soon as the first request was processed and the service getting slower and slower the more requests came in. The reason for this behavior could be seen after inserting logging commands into every single function of the binding.

Until before the first request gets in, everything works fine:

ChannelListener: OnBeginAcceptChannel
ChannelListener: OnAcceptChannel

Then, processing of the first message is done:

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...`

The channel implements the IReplyChannel interface, so it should only be possible to get a request, reply it and then close the channel. Instead of just closing the channel, the ServiceModel keeps spamming TryReceiveRequest on an already used channel regardless of the channel already being used in the past.

Is there some way to fix this properly? Why doesn't the ServiceModel close the channel after closing the reply context although it's useless to keep the channel open after it is consumed?

Etan
  • 17,014
  • 17
  • 89
  • 148
  • I could reduce the CPU load by revising the WaitForRequest method of the channel. Therefore, the TryReceiveRequest calls complete properly. However, the ServiceModel keeps spamming TryReceiveRequest. Is there some possibility to close a connection if there's nothing to read for some amount of time? – Etan Aug 12 '09 at 08:17
  • Calling close manually didn't stop the ServiceModel from calling BeginTryReceiveRequest. Only way to stop the behavior was calling Abort() manually which doesn't seem to be the correct solution for my problem. – Etan Aug 12 '09 at 12:17

1 Answers1

1

So, maybe someone still need resolving of this problem. Check the State property of channel at BeginTryReceiveRequest and EndTryReceiveRequest.

.....

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);
            }
ringess
  • 41
  • 3
  • Alternatively to returning null you can throw CommunicationObjectAbortedException or CommunicationObjectFaultedException exceptions – Marcin Zawiejski Dec 07 '18 at 12:48