I'm not sure about what would be the 'best' fit for the WCF architecture but you should consider setting your InstanceContextMode to Single as you're likely to be doing a lot of synchronization steps for what you want to do here.
How about something like this? You will obviously need to do some synchronization on the dictionary itself, but at least it's a start.
private IDictionary<string, RequestToken> RequestTokens =
new Dictionary<string, RequestToken>();
public MyResponse MyMethod(MyRequest request)
{
// get the MD5 for the request
var md5 = GetMD5Hash(request);
// check if another thread is processing/has processed an identical request
RequestToken token;
if (RequestTokens.TryGetValue(md5, out token))
{
// if the token exists already then wait till we can acquire the lock
// which indicates the processing has finished and a response is ready
// for us to reuse
lock (token.Sync)
{
return token.Response;
}
}
else
{
var token = new Token(md5);
lock (token.Sync)
{
RequestTokens.Add(md5, token);
// do processing here..
var response = ....
token.Response = response;
return response;
}
}
}
private class RequestToken
{
private readonly object _sync = new object();
public RequestToken(string md5)
{
MD5 = md5;
}
public string MD5 { get; private set; }
public object Sync { get { return _sync; } }
public MyResponse Response { get; set; }
}
To me, this is something I'd want to abstract away from my business logic, and I'll personally use PostSharp and write a little attribute to handle all this.
I've written a Memoizer attribute which does something similar in the lines of caching responses based on request but without the synchronization steps, so you could probably take a look at what I've done and modify it accordingly to achieve what you're after.