我们遇到Lucene .Net
投掷LockObtainFailedException
的锁定问题。它是一个多租户站点,每个客户在光盘上获得自己的物理搜索索引,并使用static
IndexWriters
列表,每个索引一个用于控制更改。
我们在IndexWriter
AddDocument();
DeleteDocuments();
DeleteAll();
Optimize();
Commit();
我注意到我们从未在Close()
上致电Dispose()
或IndexWriter
,并想知道这是否是良好做法,可能是问题的原因。
谢谢戴夫
答案 0 :(得分:2)
文档说是,但仅当您终止应用程序本身时-否则,否。这是IndexWriter.Dispose在Lucene.Net 4.8中的文档:
对索引提交所有更改,等待挂起的合并完成, 并关闭所有关联的文件。
这是“缓慢的正常关机”,可能需要很长时间...
请注意,这可能是一项昂贵的操作,因此,请尝试重复使用一个 作家,而不是关闭和打开一个新的。参见
Commit()
有关由某些IO设备完成写缓存的警告。
https://github.com/apache/lucenenet/blob/master/src/Lucene.Net/Index/IndexWriter.cs#L996
因此,您应该调用.Dispose()
,但是通常在关闭应用程序时仅调用一次。 It is not however clear whether you need to Dispose() its underlying objects.
您已经在致电.Commit()
,他们建议这样做。我猜你的问题实际上与线程有关。我只是在学习Lucene,但是如果我处于您的位置,我将尝试在对Lucene的所有写调用周围放置一个标准.Net锁,以便一次仅一个线程可以访问写操作。如果它解决了您的问题,则说明它正在线程化。
锁非常痛苦,Lucene的写入可能会花费很长时间,因此,如果锁解决了此问题,则可能会引入其他问题,例如2个尝试写入的线程以及1个挂起或失败的线程,具体取决于您的代码编写方式。如果确实发生了这种情况,则您可能希望实现一个Write Queue,以便线程可以快速将要写入的内容传递给诸如ConcurrentQueue之类的廉价数据结构,然后让那些写操作启动写操作(如果没有运行),并且保持出队,直到一切写完为止-然后回到睡眠状态。
答案 1 :(得分:0)
当你不再需要这个物体时使用关闭/处理总是一个好主意。开发人员公开这些方法的原因是有原因的。通常,文档提供了何时使用这些方法的其他提示。
我还建议在IDisposeable
- 块中使用每个using
- 对象,只调用Dispose()
。
这使对象能够清理和释放资源。在框架对象的情况下,这并不重要,因为垃圾收集器迟早会关心,但是在系统对象或文件系统句柄Dispose
等句柄的情况下变得很重要。这些手柄可能会保持打开状态。
在Lucene IndexWriter的情况下,我并不完全确定,但是当它使用文件作为索引时(这是我假设的),那么你就有理由调用Dispose
。< / p>
当句柄/连接/等保持打开状态时,可能会导致此类异常。所以,是的,你应该使用Close()
/ Dispose()