C#将值类型存储在缓存中

问题描述 投票:2回答:1

问题

给出一个返回网站上活动用户总数的函数:

private static readonly object Lock = new object();
public static int GetTotalActiveUsers()
{
    var cache = HttpContext.Current.Cache;
    if (cache["ActiveUsers"] == null)
    {
        lock (Lock)
        {
            if (cache["ActiveUsers"] == null)
            {
                var activeUsers = 5; // This would actually be an expensive operation
                cache.Add("ActiveUsers", activeUsers, null, Cache.NoAbsoluteExpiration,
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Normal, null);
            }
        }
    }
    return (int) cache["ActiveUsers"];
}

以这种方式将ValueType存储在缓存中的问题是它不可更新。例如:

public static void OnNewActiveUser()
{
    var total = GetTotalActiveUsers();
    total++;
}

不更新缓存的值。 (这是预期的行为)。

我正在寻找一种线程安全的方法来更新活动用户数。

解决方案1

使用锁

public static void OnNewActiveUser()
{
    lock (UpdateActiveUsersLock)
    {
        var cache = HttpContext.Current.Cache;
        var newTotal = GetTotalActiveUsers() + 1;
        cache.Insert("ActiveUsers", newTotal, null, Cache.NoAbsoluteExpiration,
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Normal, null);
    }
}

解决方案2

在int周围创建一个瘦类,将其转换为引用类型:

public class CachedInt
{
    public int Int { get; set; }
    public CachedInt(int value)
    {
        Int = value;
    }
}

然后:

public static void OnNewActiveUser()
{
    var activeUsers = GetTotalActiveUsers();
    activeUsers.Int++;
}

问题

如果可能的话,我宁愿避免使用解决方案1(它不完全适合我的设计)。是将值类型包装在一个简单的类代码中,还是解决问题的合法方法?

c# caching value-type reference-type
1个回答
0
投票

[HttpContext.Current.Cache缓存对象(引用类型),因此您需要按照建议将int(值类型)包装为引用类型。

为什么如果缓存的项目永不过期,为什么不仅仅拥有一个带有静态方法和静态成员的类来计数呢?

此外,您应该使用互锁增量来确保计数正确,并具有某种方式来了解用户何时处于非活动状态,以便可以减少计数。正如评论中指出的那样,这只会为您提供单个进程的计数。如果同一台计算机上有多个Web进程或多个服务器,则计数将是错误的-也许这就是返回5的昂贵操作:)

© www.soinside.com 2019 - 2024. All rights reserved.