I am new to Lucene, so please bear with me.
I've a class LuceneUtility which my application uses to call RequestIndexSearcher() to acquire indexSearcher object and to perform all search. Every time while return indexSearcher object I'm updating index (if anything needs to be updated) and recreated IndexSearcher object to reflect the new update (if there is any new update) but sometimes I'm getting AlreadyClosedException: this IndexReader is closed.
public class LuceneUtility
{
private static IndexSearcher _searcher;
private static Directory _directory;
private static Lazy<IndexWriter> _writer = new Lazy<IndexWriter>(() => new IndexWriter(_directory, new KeywordLowerCaseAnalyser(), IndexWriter.MaxFieldLength.UNLIMITED));
private static Object lock_Lucene = new object();
//this private constructor makes it a singleton now.
private LuceneUtility() { }
//Static constructor, opening the directory once for all.
static LuceneUtility()
{
string s ="Path of lucene Index";
_directory = FSDirectory.Open(s);
}
public static IndexSearcher IndexSearcher
{
get
{
if (_searcher == null)
{
InitializeSearcher();
}
else if (!_searcher.IndexReader.IsCurrent())
{
_searcher.Dispose();
InitializeSearcher();
}
return _searcher;
}
}
public static IndexWriter IndexWriter
{
get
{
return _writer.Value;
}
}
private static void InitializeSearcher()
{
_searcher = new IndexSearcher(_directory, false);
}
public static IndexSearcher RequestIndexSearcher()
{
lock (lock_Lucene)
{
PerformIndexUpdation();
}
return IndexSearcher;
}
/// <summary>
/// Performs Lucene Index Updation
/// </summary>
private static void PerformIndexUpdation()
{
// Performs Index Updation
}
Stacktrace:
AlreadyClosedException: this IndexReader is closed
Lucene.Net.Index.IndexReader.EnsureOpen()
at Lucene.Net.Index.DirectoryReader.IsCurrent()
at LuceneOperation.LuceneUtility.get_IndexSearcher()
at LuceneOperation.LuceneUtility.RequestIndexSearcher()
So... What's the deal here...? What am I doing wrong ?
Many thanks in advance! :)
The stack trace says it all. Likely a consumer Dispose'd _searcher via a reference returned by IndexSearcher. The following code reproduces the problem (at least one way):
Worse, IndexSearcher may Dispose an instance of_searcher referenced by a consumer, which could result in the same exception elsewhere:
Here's a skin-and-bones class that avoids the Dispose issue and the performance pitfall of frequently instantiating IndexSearcher.
writer.GetReader() is chock full of win.
I'm out of the loop with the latest Lucene.Net offers, so someone experienced with the latest version may offer a better starting point.