Friday, March 30, 2012

RECEIVING messages from a Windows service

I've done a bit of work with the External Activator but I think it may be a bit overkill for what I need to do (which is RECEIVE messages from a single queue and process them with managed code). I've tried creating a Service Broker Interface service that retrieves messages from this queue, but I notice that if I set the timeout to -1 to watch for messages indefinitely, the Service never completes the OnStart code.

I notice if I change the service's timeout to something greater than 0, the message is retrieved, but this defeats the purpose of using a Windows Service app, which I want to continuously monitor the queue. I noticed the External Activator spawns a thread to start monitoring an EventNotification queue, which I can bypass since I want to monitor the notification's target queue.

Rushi, can you point me in the right direction to create a Windows Service that constantly monitors a queue? Also, I'd like the ability to monitor multiple databases (the queue name would be the same) as well, so if that is not feasible from a Windows Service please let me know.

Also, am I sacrificing scalability by NOT using the External Activator and switching to a Windows Service (I believe the External Activator will spawn multiple instances of the processing executable)?

Thanks,

Chris

If you do not need dynamic launching of one or more instances of your service program then you are fine with your approach of writing a single threaded process (which could be a Windows Service) that receives messages from the queue serially. (Of course, you could get fancy and have multiple (but a fixed number of) threads in your process simultaneously pulling messages from the queue). But if you need the ability to control the number of instances of your service program (processes or threads) based on rate of incoming messages, you will need to either implement the external activator based on the QUEUE_ACTIVATION event notification or use the sample.

If you choose the non-activation approach (i.e. your process is always running and waiting for messages), then setting WaitforTimeout to -1 seems appropriate to me. The Service class does not have an OnStart method, so I'm not sure what you are referring to. It does have a Run() method; and if you set WaitforTimeout to -1, Run will never return. While it would be nice to have a Cancel() method that would gracefully tear down the Service class, but since the Service Broker Interface is only a sample, we did not implement that. It should be fine to terminate the process while Run() has not returned. (The transaction will automatically be rolled back).

Rushi

|||

Rushi,

Thanks for the reply. Sorry, I was using the term "service" to refer to the Service class defined in the ServiceBrokerInterface project and a Windows Service app. What I mean is, in the OnStart() method of a Windows Service app, I would need to call the Service class' Run() method, which will never return. This means that the Windows Service's OnStart() method never completes, and you end up getting an error message from the ServiceInstaller (I think). I realize this may be more of a development question, and if so, I can try posting in another forum. I was just hoping you'd seen an example of RECEIVEing messages from a queue with a timeout of -1 from a Windows Service app.

Thanks,

Chris

|||

You will need to create a Thread in the constructor of your Windows Service class which is started by the OnStart() method. The ThreadStart should point to the ServiceBrokerInterface Service.Run() method.

Hope that helps,
Rushi

|||

Rushi:

You say...."While it would be nice to have a Cancel() method that would gracefully tear down the Service class, but since the Service Broker Interface is only a sample"

What would be those graceful tear down steps ..If I want to implement one?. I can see the following...

If there are still pending messages read from the queue but not yet processed ...return such entries back to the queue by rolling back the transaction.

Implementation wise.... "cancel()" can set a flag and the Dispatch function does not dispatch messages if this flag is set ....this way messages that are already read from queue can be prevented from getting processed.

What else I am missing.?

sql

No comments:

Post a Comment