The proper way of doing this is using a queue based communication. The reason for this is scalability. You want "an instance" of your service to pick up the request, and you want "an instance" to return the result to a client right?
You can take a quick look and one of my blog posts about AppFabric Queues but they are too bulky for this. Here's how I'do it:
Create a WorkerRequest class, looking something like this
public class WorkerRequest {
string clientId;
MyTaskEnum taskToPerform;
}
Write to the Queue storage, (In my production code I'm using a wrapper which I haven't blogged about yet, but plan to :) ), add the request.
Have a worker thread listen to this queue, and when a request is received, spawn a new thread to finish it. When you're done, write to table storage with your task & client id as your keys. That way you can always check the status (a simple /GET/ request to the table) + you have decoupling & scalability already solved.
Hope it helps.
UPDATE: wanted to explain a bit more, so I decided to update the post =)
You can create a WCF web service in a "web role", which is what I would do. I blogged about it a while ago. In the same role, you create a Worker. You do that by having a class that implements RoleEntryPoint
. This class (located in Microsoft.WindowsAzure.ServiceRuntime) looks like:
public abstract class RoleEntryPoint
{
public virtual bool OnStart()
{
return true;
}
public virtual void Run()
{
Thread.Sleep(-1);
}
public virtual void OnStop()
{
}
}
You simply implement a while(true) loop in the Run, that asks the Queue if there are any new messages for processing. When such a message is received do not spawn a new one, just process it. If you want to scale it, you can scale with adding new instances. Now obviously, this can be costly, so in fact it is wise to spawn a new thread, but only to a certain limit, e.g. max 5 threads. If there are no threads in your pool, return the message to the queue (you need to call Complete()
when you're done with the message, otherwise it doesn't necessarily get deleted). It will get picked up later, or by another worker.
So, when the worker thread finishes, write the result to table storage and you're done.