简体   繁体   English

安全地使用'HttpContext.Current.Cache'

[英]Using 'HttpContext.Current.Cache' safely

I am using Cache in a web service method like this: 我在这样的Web服务方法中使用Cache

var pblDataList = (List<blabla>)HttpContext.Current.Cache.Get("pblDataList");

if (pblDataList == null)
{
    var PBLData = dc.ExecuteQuery<blabla>(@"SELECT blabla");

    pblDataList = PBLData.ToList();

    HttpContext.Current.Cache.Add("pblDataList", pblDataList, null,
        DateTime.Now.Add(new TimeSpan(0, 0, 15)),
        Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
}

But I wonder, is this code thread-safe? 但我想知道,这段代码是否是线程安全的? The web service method is called by multiple requesters. Web服务方法由多个请求者调用。 And more then one requester may attempt to retrieve data and add to the Cache at the same time while the cache is empty. 当缓存为空时,多个请求者可能会尝试检索数据并同时添加到Cache中。

The query takes 5 to 8 seconds. 查询需要5到8秒。 Would introducing a lock statement around this code prevent any possible conflicts? 是否会围绕此代码引入锁定语句以防止任何可能的冲突? (I know that multiple queries can run simultaneously, but I want to be sure that only one query is running at a time.) (我知道多个查询可以同时运行,但我想确保一次只运行一个查询。)

The cache object is thread-safe but HttpContext.Current will not be available from background threads. 缓存对象是线程安全的, 但后台线程无法使用HttpContext.Current This may or may not apply to you here, it's not obvious from your code snippet whether or not you are actually using background threads, but in case you are now or decide to at some point in the future, you should keep this in mind. 这可能适用于您,也可能不适用于您,从您的代码段开始,您是否实际使用后台线程并不明显,但如果您现在或将来某个时候决定,您应该牢记这一点。

If there's any chance that you'll need to access the cache from a background thread, then use HttpRuntime.Cache instead. 如果您有可能需要从后台线程访问缓存,请改用HttpRuntime.Cache

In addition, although individual operations on the cache are thread-safe, sequential lookup/store operations are obviously not atomic. 此外,虽然缓存上的单个操作是线程安全的,但顺序查找/存储操作显然不是原子操作。 Whether or not you need them to be atomic depends on your particular application. 您是否需要它们是原子的取决于您的特定应用。 If it could be a serious problem for the same query to run multiple times, ie if it would produce more load than your database is able to handle, or if it would be a problem for a request to return data that is immediately overwritten in the cache, then you would likely want to place a lock around the entire block of code. 如果同一个查询多次运行可能是一个严重的问题,即它是否会产生比数据库能够处理的更多的负载,或者如果请求返回的数据立即被覆盖,则会出现问题缓存,那么你可能想要锁定整个代码块。

However, in most cases you would really want to profile first and see whether or not this is actually a problem. 但是,在大多数情况下,您真的想首先分析并查看这是否真的是一个问题。 Most web applications/services don't concern themselves with this aspect of caching because they are stateless and it doesn't matter if the cache gets overwritten. 大多数Web应用程序/服务都不关心缓存的这一方面,因为它们是无状态的,如果缓存被覆盖则无关紧要。

You are correct. 你是对的。 The retrieving and adding operations are not being treated as an atomic transaction. 检索和添加操作不会被视为原子事务。 If you need to prevent the query from running multiple times, you'll need to use a lock. 如果您需要阻止查询多次运行,则需要使用锁定。

(Normally this wouldn't be much of a problem, but in the case of a long running query it can be useful to relieve strain on the database.) (通常情况下这不是什么大问题,但是对于长时间运行的查询,可以减轻数据库的压力。)

I believe the Add should be thread-safe - ie it won't error if Add gets called twice with the same key, but obviously the query might execute twice. 我相信Add应该是线程安全的 - 即如果使用相同的键调用Add两次,它将不会出错,但显然查询可能会执行两次。

Another question, however, is is the data thread-safe . 然而,另一个问题是数据线程安全 There is no guarantee that each List<blabla> is isolated - it depends on the cache-provider. 无法保证每个List<blabla>都是隔离的 - 它取决于缓存提供者。 The in-memory cache provider stores the objects directly, so there is a risk of collisions if any of the threads edit the data (add/remove/swap items in the list, or change properties of one of the items). 内存缓存提供程序直接存储对象,因此如果任何线程编辑数据(在列表中添加/删除/交换项目,或更改其中一个项目的属性),则存在冲突风险。 However, with a serializing provider you should be fine. 但是,对于序列化提供程序,您应该没问题。 Of course, this then demands that blabla is serializable... 当然,这要求blabla可序列化......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM