单例模式中的“值不能为空”错误

时间:2011-03-08 12:22:39

标签: c# wcf design-patterns singleton

我有一个实现单例模式的类,如下所示:

public class SearchSingletonObject
{
    private static SearchSingletonObject foundation = null;
    public SearchObject Object= null;
    private static StringCollection views = null;
    private static object control = new object();
    public IEnumerable<string> blacklist = null;
    public static void ClearFoundation()
    {
        foundation = null;
    }
    public static SearchSingletonObject Foundation
    {
        get
        {
            if (foundation == null)
            {
                lock (control)
                {
                    if (foundation == null)
                    {

                        foundation = new SearchSingletonObject();
                        var blacks = File.ReadAllText(HostingEnvironment.ApplicationPhysicalPath + "\\blacklist.txt");
                        foundation.blacklist = blacks.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrEmpty(x) || x != " ");
                        views = new StringCollection();
                        var items = ConfigurationManager.AppSettings["SearchView"].Split(',');
                        foreach (var item in items)
                        {
                            views.Add(item);
                        }
                        foundation.Object = new SearchObject(ConfigurationManager.AppSettings["ContentDistributor"],
                                                                ConfigurationManager.AppSettings["Port"],
                                                                views);
                    }
                }
            }
            return foundation;
        }
    }
    public SearchSingletonObject()
    {

    }
}

我们在wcf休息服务中使用此类。但是在非周期性间隔中,我们得到“Value not not null”错误。这是我的日志文件:

08.03.2011 11:40:39 ERROR Message : Value cannot be null.
Parameter name: source

StackTrace : at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2           predicate)
at Search.Service.SearchService.Search(String keyword, Int32 offset, Int32 hit, String navstate, String username, Boolean issecure, Int32 suggest, String sortref, String fields, Int32 IsFirstSearch, String misspelled, String category) in D:\tfs\Hey\HeyRestApi\HeyService\HeyService.cs:line 68

日志文件提到我服务中的下面一行:

var blacks = SearchSingletonObject.Foundation.blacklist.Where<string>(x => item.Equals(x)).FirstOrDefault();

奇怪的是,“黑名单”对象获得空值。出错后,我们必须重置IIS,以使应用程序正常工作。我们无法在本地服务器上重现错误。它恰好发生在我们的客户生产环境中。

我们如何解决这个问题以及这个奇怪错误的原因是什么?

提前致谢,

1 个答案:

答案 0 :(得分:2)

Double-checked locking is broken

简短说明:

即使foundation非空,没有锁定,您也无法确定基金会的成员从处理器的角度来看是非空的。

您需要删除锁定之外的if语句。

<强>更新

更好的解决方案是将基础标记为易变的:

private static volatile SearchSingletonObject foundation = null;

The need for volatile modifier in double checked locking in .NET有更多详情。