我正在开发一个Web服务,它应该获取一些数据,将它们用于查询,在Solr中搜索并返回相应的结果!它工作正常但我需要它只初始化Solr一次到目前为止我已经得到了这个:
private static bool initialized = false;
[WebMethod]
public XmlDocument getContributor(string name,string email)
{
if (!initialized)
{
Startup.Init<SolrSearchResult>("http://Host:44416/solr");
initialized = true;
}
if (string.IsNullOrEmpty(email))
{
return SolrSearchResult.SearchData(name);
}
return SolrSearchResult.SearchDataWithEmail(name, email);
}
但我认为当多个用户使用时,它将无法正常工作!我需要一种更聪明的方法来解决这个问题!我很感激任何建议!
P.S:我见过SampleSolrApp,在Application_Start中使用了startup.init,但我不知道这里的等价物是什么。
答案 0 :(得分:1)
确保Startup.Init
在对getContributor
方法进行多次并发调用时永远不会被调用的一种方法是引入互斥锁来同步对该块的访问代码。
在你的情况下,我首先介绍一个静态对象来锁定:
private static readonly object syncRoot = new object();
然后将代码中的那部分包含在lock语句中:
lock (syncRoot)
{
// only 1 thread ever enters here at any time.
if (!initialized)
{
Startup.Init<SolrSearchResult>("http://Host:44416/solr");
initialized = true;
// no more threads can ever enter here.
}
}
lock
关键字确保一个线程不进入代码的关键部分,而另一个线程处于临界区。如果另一个线程试图输入一个被锁定的代码块,它将等待该对象被释放。
作为旁注;您可以使用一些技术来优化此代码,进一步称为双重检查锁定,这样可以避免每次调用getContributor
时获得锁的性能成本较低:
// check to see if its worth locking in the first place.
if (!initialized)
{
lock (syncRoot)
{
// only 1 thread ever enters here at any time.
if (!initialized)
{
Startup.Init<SolrSearchResult>("http://Host:44416/solr");
initialized = true;
// no more threads can ever enter here.
}
}
}
当initialized
永远不需要成为false
并且您不需要Startup.Init
以后再次运行时,无论出于何种原因,这都有效。另外,你可能会遇到使用此代码的问题。