views:

499

answers:

4

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?

A: 

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.

Steve
+2  A: 

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.

Tom A
This is great tom, but what should I build the server component as? An asmx web service, a windows service, or a WCF service?
Alex
.Net 2.0 asmx web service works fine. That has built-in support for the async pattern. It's true that the queuing is built into WCF (I don't mean msmq, but just serializing calls), but the BAackgroundWorker is simpler.
Tom A
Tom thankyou for expanding on your answer. I am going to try and implement this tonight and no doubt i'll have a few questions tomorrow morning! Thanks everyone for responding.
Alex
My only issue with this method is that it seems I am kind of kludging a queue by locking the simulation queue. However, I can sort of see how I can make it a bit more 'queuey' using this backgroundworker method. I'll see how I go.
Alex
Re: Queue. Yep, one step at a time.I just consolidated my edits to make the answer more readable and added a note that the cancellation dictionary needs to be static.Good luck!
Tom A
Oh, yes, and this approach uses the built-in queues for locks and for the threadpool. BW threads queue up behind the lock, and when threadpool is used up new BWs queue up for threads. But you could build your own queued access to the simulator resource, of course.
Tom A
@Jacob: So, what worked?
Tom A
Tom: Sorry for the belated response, I'd forgotten I hadnt answered this question. The ASMX/BW thread combo worked well for me. I'll look at WCF next time I do this because it does seem very powerful, but your idea on how to implement this quickly worked very well and kept the client happy.
Alex
+1  A: 

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.

Cheers, Marc

marc_s
I agree WCF is a good approach for this -- it can even queue incoming requests by setting "one at a time" request processing (kludgy). But using msmq binding creates complexity for cancellation and completion notification.
Tom A
Yes - MSMQ has its complexities - but also its rewards! :-) It's always a matter of priorities and requirements. "It depends" is the ultimate answer in IT :-)
marc_s
+1  A: 

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.

Jonathan C Dickinson
I agree the in-memory queue of background worker tasks is not at all fault tolerant, but does the solution require that? As I noted in comment to @marc_s MSMQ makes cancellation and completion much more complicated than does a simple async web service call.
Tom A
And an async web service would use callbacks, not polling, for completion notification or progess updates.
Tom A
@Tom, yes, true, an async webservice will suffice: but what the heck: WCF has it built in :).
Jonathan C Dickinson