.NET Best approach to implementing client/server queuing model with external app?

1.2k Views Asked by At

Here is the spec:

  1. Multiple clients using a WPF winforms application on their local machines
  2. Clients initiate requests to the server to execute a simulation. This initiation should probably be via a web service but other suggestions are welcome
  3. Requests are queued on the server
  4. Server sends out sequential requests to the simulation model via a web service.
  5. Server informs client that simulation is complete

An additional requirement is to have a client cancel a request they have previously made. Note that we dont have to worry about sending too much data down the pipe, we are only sending confirmation that a particular simulation run completed (or failed)

To begin with I thought I could do all of this with a single asmx web service, but now I think that might be unwieldy. WCF seems like another option, but I am not familiar with it and it seems far more complicated than the functionality I need.

Any ideas?

4

There are 4 best solutions below

7
On BEST ANSWER

Client: To get the completion notification you will need to use the async design pattern when calling the web service from the client. If you use "add web reference" to create the client proxy the async pattern methods are generated for you. See: "Access Web Services Asynchronously in .NET Design Patterns".

Server: A vanilla .Net 2.0 asmx web service can queue the incoming calls for serial processing on the server. You can build a simple dispatcher using the BackgroundWorker class. The dispatcher takes each incoming request and assigns it to a background thread. To serialize the threads have the worker method place a lock around the simulation call. See this example of using BackgroundWorker threads.

Cancellation: To handle cancellation have the server return a unique id with its response to the client request and also insert the id and the associated background workworker reference into a dictionary. A CancelSimulation method on the web service accepts the id, looks up the BackgroundWorker ref in the dictionary and calls its CancelAsync method. Remove the dictionary entry when the task completes or is cancelled. The dictionary needs to be shared by all web service calls so it should be static/Shared. Fortunately, a static dictionary is thread-safe.

0
On

You should look more closely at WCF. I've written a custom library for work that takes care of some odd configuration stuff, but you can write an excellent webservice in a couple of dozen lines of code with WCF. It is highly extensible. The only problem is that it takes awhile to "get" it, but once you do its really, really simple. Good luck.

2
On

WCF seems like another option, but I am not familiar with it and it seems far more complicated than the functionality I need.

I would strongly urge you to take a really good look at WCF - yes, it might be a bit more daunting at first, but it gives you a lot of flexibility by means of configuration, rather than having to code to a particular transport medium (e.g. web service vs. message queue).

Since you're saying explicitly that the client will send requests to a queue on the server - why not just use a queue-based messaging system like MSMQ in the first place?

With WCF on the server and client, you have the ability to quickly switch between using MSMQ vs. using a "regular" HTTP SOAP call vs. using e.g. a REST call - all in the config. This kind of flexibility is worth investing a bit of time getting to learn it, IMHO.

3
On

You should look at WCF. Using a web service + polling could kill your server (unless you don't have that many clients) - just look at Twitter. WCF has a persistent connection that should suite you perfectly.

As for the queuing, add System.Messaging as a reference and use MSMQ. I can't remember if there is a MSMQ transport for WCF, but I am sure you can find one. Using that would kill two birds with one stone. If you want to use MSMQ your server will need to be on a Windows domain.

Otherwise, I strongly recommend you write events to a DB and pick them out from there as the worker thread(s) finish up. Keeping them in a in-memory queue isn't very fault tolerant.