每个Web请求的唯一锁定对象

时间:2014-12-20 01:22:41

标签: c# wcf parallel-processing locking

我正在构建一个WCF翻译服务。该服务使用谷歌翻译的网络API。 为避免重新获取常用搜索查询,该服务会保留上次搜索的内存缓存。 搜索功能首先检查缓存,然后才向谷歌发出请求。 最后一个重要细节 - 每次请求到达时,我构造一个字符串作为它的关键 - 它由搜索词和两种语言命名代码组成 - 所以每个特定搜索它是唯一的。

问题是: 假设两个确切的请求同时到达,我想从整个搜索功能中锁定第二个请求,这样当它进入时它将找到已经由第一个输入到缓存的搜索结果。如果有不同的请求到达,我想让它进入。

我的想法是使用我构造的字符串来锁定,因为它对于每个精确搜索(相同的搜索词,相同的语言)是唯一的。这会给出我描述的结果吗?

感谢您阅读此内容(:

请参阅下面的代码示例 - 再次感谢!

public async Task<TranslationResult> TranslateAsync(Langueges From, Langueges To, string Content)
{
   string key = Content + From.ToString() + To.ToString();
   lock(key)
   {
      //look for the search result in the cache
      //if not found, request from google and store result in the memory cache
   }
}

3 个答案:

答案 0 :(得分:0)

这样的东西?

// this cache is probably going to be the application level cache in asp.net
// but using Dictionary as an example in this case
Dictionary<string,TranslationResult> cache = new ...
private static object syncRoot = new Object();

if (!cache.ContainsKey(key)
{
    lock(syncRoot)
    {
        // this double checks is not a mistake.
        // the second request would check for existence of
        // the key once it acquire the lock
        if (!cache.ContainsKey(key) {
            // send request to google then store the result 
        }
        else {
            return cache[key];
        }
    }
}
else
{
    return cache[key];
}

答案 1 :(得分:0)

我认为你不会得到你正在寻找的行为:变量“key”将始终是新创建的对象,并且当前线程将始终立即被授予锁定。我不相信字符串实习会在这里发挥作用,因为“关键”变量不是文字。如果“key”是一个实习字符串,那么它可能会像你想要的那样工作,但这将是一个奇怪的副作用。

怎么办?考虑使用ConcurrentDictionary.GetOrAdd方法。你的“关键”变量将成为关键参数。如果密钥不在缓存中,则将调用valueFactory。您的valuefactory实施应该将呼叫发送给Google。这是ConcurrentDictionary是线程安全的,因此您不需要显式锁定。

答案 2 :(得分:0)

如果两个确切的请求同时到达,则返回其中一个与orginaly :) 你可以知道哪个不是被解密的,然后再发送它。我之前做过这个