views:

220

answers:

2

I have a Windows Service that takes the name of a bunch of files and do operations on them (zip/unzip, updating db etc). The operations can take time depending on size and number of files sent to the service.

(1) The module that is sending a request to this service waits until the files are processed. I want to know if there is a way to provide a callback in the service that will notify the calling module when it is finished processing the files. Please note that multiple modules can call the service at a time to process files so the service will need to provide some kind of a TaskId I guess.

(2) If a service method is called and is running and another call is made to the same service, then how will that call be processed(I think there is only one thread asociated with the service). I have seen that when the service is taking time in processing a method, the threads associated with the service begin to increase.

+2  A: 

WCF does indeed offer duplex bindings which allow you to specify a callback contract, so that the service can call back to the calling client to notify.

However, in my opinion, this mechanism is rather flaky and not really to be recommended.

In such a case, when the call causes a fairly long running operation to happen, I would do something like this:

If you want to stick to HTTP/NetTcp bindings, I would:

  • drop off the request with the service, and then "let go" - this would be a one-way call, you just drop off what you want to have done, and then your client is done
  • have a status call that the client could call after a given time to find out whether or not the results of the request are ready by now
  • if they are, there should be a third service call to retrieve the results

So in your case, you could drop off the request to zip some files. The service would go off and do its work and store the resulting ZIP in a temporary location. Then later on the client could check to see whether the ZIP is ready, and if so, retrieve it.

This works even better over a message queue (MSMQ) which is present in every Windows server machine (but not a lot of people seem to know about it or use it):

  • your client drops off the request on a request queue
  • the service listens on that request queue and fetches request after request and does it works
  • the service can then post the results to a result queue, on which your callers in turn are listening

Check out how to do all of this efficiently by reading the excellent MSDN article Foudnations: Build a queue WCF Response Service - highly recommended!

A message-queue based systems tends to be much more stable and less error-prone that a duplex-/callback-contract based system, in my opinion.

marc_s
I cannot use MSMQ because this Windows Service runs on user's system (XP, Vista, 7) and is part of the product that the user downloads. So a GetStatus() is the way to go I guess. Wondering how complex will it get with multiple commands executing at the same time.
A9S6
@A9S6: WCF creates a brand-new service instance for each call - so there's really no issues with multiple requests at the same time - each has its own, little, isolated service class instance.
marc_s
@marc_s: Do you mean that a new instance of the Service Class(ServiceBase inherited) is created on each call? I thought this happened only with Web Services and not Windows Services. So, one should not put initialization in this class unless required on each method call?
A9S6
@A9S6: yes - every call to a WCF service (by default) causes a new service class instance to be created to handle the request. But that is a **good thing** !!
marc_s
A: 

(1) The simplest way to achieve this is with a taskId as you note, and then have another method called IsTaskComplete with which client can check whether the task has been completed.

(2) Additional calls made to the service will start new threads.

edit: the default service behaviour is to start new threads per call. The configurable property is Instance Context Mode, and can be set to PerCall, PerSession, or Shareable.

Kirk Broadhurst
Are you sure about (2)? Is there an article that explains this behavior or a way to close these service threads?
A9S6
In my experience new threads are started, but this link indicates that the service can be configured be per-call, per-session, or singleton. http://codeidol.com/csharp/wcf/Instance-Management/ - news to me!
Kirk Broadhurst