ASP.NET MVC竞争条件?工厂单例静态字典

时间:2014-09-03 00:57:17

标签: c# singleton factory

我有以下单例类,它用作在我的Web应用程序中创建对象的工厂。但是,我看到我在负载测试期间遇到了某种竞争条件。我应该遵循更好的模式吗?

public class SearchProviderFactory {
    private static SearchProviderFactory factory = null;        
    private static Dictionary<string, Type> providerMap = new Dictionary<string, Type>();

    private SearchProviderFactory() {
        // Error on the line below
        providerMap.Add("company_name", Type.GetType("MyApp.CompanySearchProvider"));
        providerMap.Add("job_title", Type.GetType("MyApp.JobTitleSearchProvider"));
    }

    public static SearchProviderFactory Instance {
        get {
            if (factory == null) {
                factory = new SearchProviderFactory();
            }

            return factory;
        }
    }
}

我收到以下错误,即使私有构造函数似乎永远不会被调用多次。

System.ArgumentException: An item with the same key has already been added.
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at MyApp.SearchProviderFactory..ctor() in c:\MyApp\_scm\app\src\trunk\MyApp\SearchProviderFactory.cs:line 7

1 个答案:

答案 0 :(得分:1)

您的代码几乎与MSDN article上讨论C#中Singleton实现的示例代码相同。那篇文章非常好,我推荐它。

他们的建议是添加一个lock()语句来实现一个关键部分,使用。在您的代码中,这将是:

public class SearchProviderFactory {
    private static volatile SearchProviderFactory factory;        
    private static Dictionary<string, Type> providerMap = new Dictionary<string, Type>();

    private SearchProviderFactory() {
        // Error on the line below
        providerMap.Add("company_name", Type.GetType("MyApp.CompanySearchProvider"));
        providerMap.Add("job_title", Type.GetType("MyApp.JobTitleSearchProvider"));
    }

    public static SearchProviderFactory Instance {
        get {
            if (factory == null) {
                lock (providerMap)
                {
                    if (factory == null) {
                        factory = new SearchProviderFactory();
                    }
                }
            }

            return factory;
        }
    }
}

我没有编译这段代码,更不用说对它进行压力测试了。如果你试试,请告诉我这是否有效!