在ASP.NET MVC应用程序中创建的多个单例实例

时间:2018-06-13 16:33:05

标签: c# asp.net-mvc caching singleton

我有一个ASP.NET MVC 5应用程序,它使用LightInject作为DI容器,我有一个Service类,它位于我的VS解决方案中的另一个类库中。

My Solution
 |____ASP.NET MVC Web App (async controller calls service method)
 |____Service Class Library
    |____InMemoryCacheService (Singleton)

此服务类是指我在Jon Skeet's preferred singleton pattern方法(简化版)之后创建的InMemoryCacheService Singleton类:

public sealed class InMemoryCacheService
{
private static readonly InMemoryCacheService _singleton = new InMemoryCacheService();

// A private constructor to restrict the object creation from outside
static InMemoryCacheService()
{
}

private InMemoryCacheService()
{
    Log.Info("New In Memory Cache Service instance created!");
}

public static InMemoryCacheService Instance
{
    get
    {
        return _singleton;
    }
}

public Dictionary<string, ConcurrentDictionary<string, Changeset>> ChangesetCacheDictionary
{
    get { return _changesetCacheDictionary; }
    set { _changesetCacheDictionary = value; }
}


public string GetChangesetCacheKey(string releaseWorkItemId)
{
    return $"{releaseWorkItemId}_{CHANGESET_CACHE}";
}


public T GetOrSet<T>(string cacheKey, TimeSpan duration) where T : class
{
    var item = MemoryCache.Default.Get(cacheKey) as T;
    if (item == null)
    {
        lock (CacheLockObject)
        {
            item = GetItemFromCacheType<T>(cacheKey);
            MemoryCache.Default.Add(cacheKey, item, DateTime.Now.Add(duration));
        }
    }

    return item;
}

private T GetItemFromCacheType<T>(string cacheKey) where T : class
{
    T result = null;
    var tokens = cacheKey.Split('_');
    var releaseWorkItemId = tokens[0];
    var cacheType = tokens[1];
    switch (cacheType)
    {
        case CHANGESET_CACHE:
            result = GetChangesetitItem<T>(releaseWorkItemId);
            break;
    }

    return result;
}

private T GetChangesetitItem<T>(string releaseWorkItemId) where T : class
{
    T result = null;
    if (ChangesetCacheDictionary == null)
    {
        ChangesetCacheDictionary = new Dictionary<string, ConcurrentDictionary<string, Changeset>>()
            {
                { releaseWorkItemId,new ConcurrentDictionary<string, Changeset>() }
            };
    }
    else if (!ChangesetCacheDictionary.ContainsKey(releaseWorkItemId))
    {
        ChangesetCacheDictionary.Add(releaseWorkItemId, new ConcurrentDictionary<string, Changeset>());
    }
    result = ChangesetCacheDictionary[releaseWorkItemId] as T;
    return result;
}

}

我遇到的问题是,在调试时我注意到正在创建我的Singleton类的多个实例!我的单例实例是从异步控制器方法引用来生成报告,该报告调用我的服务和服务使用单例并行异步任务。

我第一次运行报表时初始化Singleton并按预期填充缓存。但是我第二次或第三次运行报告时会创建一个新实例。当我在笔记本电脑中运行我的webapp时似乎没有发生这种情况,我只在沙箱服务器中看到它。什么可能是错的想法?我的理解是我的Singleton只会创建一次。

以下是我的服务如何使用Singleton InMemoryCacheService

的示例
GitCommitCache = InMemoryCacheService.Instance.GetOrSet<ConcurrentDictionary<string,GitCommit>>(gitCommitCacheKey,new TimeSpan(1, 0, 0, 0));

0 个答案:

没有答案