We have a WCF service that is processing incoming messages in the following manner:
public bool ProcessMessage(string message)
{
var returnValue = GetReturnValue();
Task.Run(() => {
//do some things with the message
UpdateDatabase();
SendRepliesOverNetwork();
});
return returnValue;
}
In an effort to process as many messages as possible, we added the task here. We want to return the returnValue to the caller as quickly as possible and let the Task do its thing.
My question: is there is any advantage to using the awaitable async database calls and/or using async methods for the replies over the network?
I'm cautious, as I think this may create too much context switching. We're already seeing the app using 100+ threads under load.
First, I suggest you take a step back and really ask if returning early is a good idea. What you're doing is usually dangerous; you're returning the "OK" to the client before doing the actual processing. This is only a good idea if your client knows that "returnValue" doesn't mean the action is complete and only considers it complete upon receiving the "SendReplies".
That said, yes, you should see some benefit from making everything asynchronous that you can. If all your tasks are nonblocking, you'll get better use out of your thread pool (less context switching).
public bool ProcessMessage(string message)
{
var returnValue = GetReturnValue();
Task.Run(async () => {
//do some things with the message
await UpdateDatabaseAsync();
await SendRepliesOverNetworkAsync();
});
return returnValue;
}
I can see a couple of potential problems with this approach.
Firstly, if you're hosting your WCF service in IIS, using background threads that live longer than the request is a big no-no. When a request is complete, IIS is at liberty to tear down the whole AppDomain
which will abort all background work with extreme predjudice!
Secondly, WCF will throttle requests if existing work is mounting up. With this pattern, you are handling the requests quickly and the amount of work queued for the thread pool may increase without limit.
You could try using WCF asynchronous service methods. This would free up threads that are just waiting for IO - your database and network access - which can improve throughput.
There's an in-depth article about this approach here: Dan Rigsby: Async Operations in WCF
Also, there's a section in MSDN here: WCF: Synchronous and Asynchronous Operations