Lucene - AlreadyClosedException:此IndexReader已关闭

时间:2017-01-03 06:22:50

标签: c# lucene lucene.net

我是Lucene的新手,所以请耐心等待。

我有一个类LuceneUtility,我的应用程序使用它来调用RequestIndexSearcher()来获取indexSearcher对象并执行所有搜索。 每次返回indexSearcher对象时我都在更新索引(如果有什么需要更新)并重新创建IndexSearcher对象以反映新的更新(如果有任何新的更新)但有时我得到AlreadyClosedException:这个IndexReader已关闭。 / p>

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 
    }

堆栈跟踪:

     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()

那么......这里有什么交易......?我做错了什么?

非常感谢提前! :)

1 个答案:

答案 0 :(得分:2)

堆栈跟踪说明了一切。可能是消费者通过IndexSearcher返回的引用Dispose&#39; _searcher。以下代码再现了问题(至少有一种方法):

Lucene.Net.Index.IndexWriter sw = LuceneUtility.IndexWriter;
Lucene.Net.Search.IndexSearcher ref1 = LuceneUtility.IndexSearcher;
ref1.Dispose();
// this next call throws at _searcher.IndexReader.IsCurrent()
// because _searcher has been Dispose'd 
Lucene.Net.Search.IndexSearcher ref2 = LuceneUtility.IndexSearcher; 

更糟糕的是,IndexSearcher可能会处理由使用者引用的实例of_searcher,这可能会在其他地方导致相同的异常:

Lucene.Net.Search.IndexSearcher ref1 = LuceneUtility.IndexSearcher;
// index some documents with the writer
Lucene.Net.Search.IndexSearcher ref2 = LuceneUtility.IndexSearcher;
// acquiring ref2 Dispose'd ref1 because index changed so AlreadyClosedException is thrown
int freq = ref1.DocFreq(new Lucene.Net.Index.Term("text", "RamblinRose"));

这是一个皮肤和骨骼类,它避免了Dispose问题和频繁实例化IndexSearcher的性能缺陷。

public static class MySingletonIndex
{
    private static IndexWriter writer;

    public static void Open(string path)
    {
        if (writer != null)
            throw new Exception("MySingletonIndex is already open");
        // ram directory is a nice option for early stages and experimentation.
        Directory d = path == null ? new RAMDirectory() : (Directory)FSDirectory.Open(path);
        writer = new IndexWriter(d, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
    }

    public static void Close()
    {
        if (writer == null) return;
        writer.Dispose();
        writer = null;
    }
    /// <summary>
    /// Caller must Dispose the IndexSearcher returned.
    /// </summary>
    /// <returns>IndexSearcher</returns>
    public static IndexSearcher GetSearcher()
    {
        if (writer == null)
            throw new Exception("MySingletonIndex is closed");
        return new IndexSearcher(writer.GetReader());           
    }
}

writer.GetReader()充满了胜利。

我已经退出了最新的Lucene.Net优惠,所以有经验的最新版本可能会提供更好的起点。