锁定ASP.NET WebAPI中的不同线程

时间:2015-05-14 02:52:29

标签: c# asp.net asp.net-web-api2

我有一个场景,我需要在第一次调用时暂时缓存来自webapi的信息。使用相同的参数,这个API可以每秒调用几次。

由于性能限制,我不希望每次调用获取数据并将其放入内存缓存中,因此我实现了一个带有Semaphores的系统,尝试允许一个线程初始化缓存,然后允许其余的只是查询缓存。

我已经删除了代码,以显示我目前正在做的事情。

      private static MemoryCacher memCacher = new MemoryCacher();
      private static ConcurrentDictionary<string, Semaphore> dictionary = new ConcurrentDictionary<string, Semaphore>();              


      private async Task<int[]> DoAThing(string requestHash)
      {           
             // check for an existing cached result before hitting the dictionary
             var cacheValue = memCacher.GetValue(requestHash);
             if (cacheValue != null)
             {                      
                   return ((CachedResult)cacheValue).CheeseBurgers;
             }

             Semaphore semi;
             semi = dictionary.GetOrAdd(requestHash, new Semaphore(1, 1, requestHash));                  
             semi.WaitOne();

             //It's possible a previous thread has now filled up the cache. Have a squiz.
             cacheValue = memCacher.GetValue(requestHash);
             if (cacheValue != null)
             {                 
                    dictionary.TryRemove(requestHash);    
                    semi.Release();             
                    return ((CachedResult)cacheValue).CheeseBurgers;                           
             }

             // fetch the latest data from the relevant web api
             var response = await httpClient.PostAsync(url, content);                     

             // add the result to the cache
             memCacher.Add(requestHash, new CachedResult() { CheeseBurgers = response.returnArray }, DateTime.Now.AddSeconds(30));

             // We have added everything to the cacher so we don't need this semaphore in the dictonary anymore:
             dictionary.TryRemove(requestHash);

             //Open the floodgates
             semi.Release()


             return response.returnArray;
      }

不幸的是,有很多奇怪的问题,一次有多个线程设法通过WaitOne()调用,然后释放时由于信号量的计数限制而导致中断。 (确保一次只有一个信号量正在工作) 我已经尝试过使用Mutexes和Monitors,但是由于IIS不能保证API调用总是在同一个线程上运行,因此当尝试在另一个线程中释放互斥锁时,会导致它定期失败。

任何有关实施此方法的建议都会受到欢迎!

0 个答案:

没有答案