4
votes

I've created a WCF service that listens to a private MSMQ for jobs. I've throttled my service so that it will only handle one job at a time (maxConcurrentInstances = 1). The problem I have is that when two messages are submitted and I inspect the queue through my Computer Management console, it's empty. I expect there to be one pending message. When I submit three messages, I'll see one pending message in the MSMQ. From reading MSDN, it looks like the ServiceHost is holding the next job in memory until the current job is done, but I can't find a way to turn it off so that the it doesn't hold the message in memory. Does anyone know of a way to make it so that the ServiceHost won't hold the pending message in memory and leave it in the queue? Thanks!

  <configuration>
  <system.serviceModel>
    <services>
      <service
          name="MyService"
          behaviorConfiguration="DefaultServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/MyService/"/>
          </baseAddresses>
        </host>
        <endpoint 
                  address="net.msmq://localhost/private/MyService"
                  binding="netMsmqBinding" bindingConfiguration="MsmqBindingNoSecurity"
                  contract="IMyService" />
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultServiceBehavior">
          <serviceMetadata httpGetEnabled="True"/>
          <serviceThrottling 
            maxConcurrentCalls="1"
            maxConcurrentSessions="1"
            maxConcurrentInstances="1"
          />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <bindings>
      <netMsmqBinding>
        <binding name="MsmqBindingNoSecurity"
             useActiveDirectory="false"
             exactlyOnce="false">
          <security mode="None">
            <transport
               msmqAuthenticationMode="None"/>
          </security>
        </binding>
      </netMsmqBinding>
    </bindings>

  </system.serviceModel>
</configuration>
2
This is my first post on StackOverflow, so I'm a newbie at this. Let me know if I need to provide more detail or if there's more I can do to help the community answer my question.MrE

2 Answers

0
votes

If you can't use a transactional queue (e.g. if you are using netMessagingBinding) you can use the ReceiveContext attribute for more fine-grained control. Its well explained by Juval Lowy here in his book:

http://books.google.co.uk/books?id=PvNrurEhmiEC&pg=PA500&lpg=PA500&dq=ReceiveContext&source=bl&ots=ChDvHuH_Jq&sig=XHhiz2ebmXuu0QNYcBYhtlN99p4&hl=en&sa=X&ei=XgYmUo3kHOOH0AW--oHoCg&ved=0CFsQ6AEwCTgK#v=onepage&q=ReceiveContext&f=false

Also see this MSDN article to see how specifically it can be used in the netMessagingBinding scenario (I know that's not directly relevant to your question but the principal still holds)

http://msdn.microsoft.com/en-us/library/hh532034(VS.103).aspx

0
votes

I have also noticed this behaviour in netMsmqBinding and as far as I know it's not addressable from the service end.

This is only an issue if you're not using transactional queues whereby a failure in your service could result in the in-memory message being dropped permanently.

If you use transactional queues even though the message has been read from the inbound queue it's actually still there on the queue (but it becomes "invisible"). If you suffer a failure on your service at this time the message will become re-queued and then processed when you come back up.

If you cannot use transactional queueing then the only way you can address this is to do so from the client, which means checking to see if a message has been transmitted before making another call. This can be done using System.Messaging or I assume you could bake this into a custom behaviour.