我有一个抓取网站并将内容作为lucene索引文件写入物理目录的应用程序。
当我为此目的使用线程时,由于锁定而导致写入错误或错误。
我想使用多个线程并写入索引文件而不会遗漏任何线程的任务。
public class WriteDocument
{
private static Analyzer _analyzer;
private static IndexWriter indexWriter;
private static string Host;
public WriteDocument(string _Host)
{
Host = _Host;
Lucene.Net.Store.Directory _directory = FSDirectory.GetDirectory(Host, false);
_analyzer = new StandardAnalyzer();
bool indexExists = IndexReader.IndexExists(_directory);
bool createIndex = !indexExists;
indexWriter = new IndexWriter(_directory, _analyzer, true);
}
public void AddDocument(object obj)
{
DocumentSettings doc = (DocumentSettings)obj;
Field urlField = new Field("Url", doc.downloadedDocument.Uri.ToString(), Field.Store.YES, Field.Index.TOKENIZED);
document.Add(urlField);
indexWriter.AddDocument(document);
document = null;
doc.downloadedDocument = null;
indexWriter.Optimize();
indexWriter.Close();
}
}
对于上面的课程,我传递的是这样的值:
DocumentSettings writedoc = new DocumentSettings()
{
Host = Host,
downloadedDocument = downloadDocument
};
Thread t = new Thread(() =>
{
doc.AddDocument(writedoc);
});
t.Start();
如果我在t.Join();
之后添加t.Start();
代码对我有用而没有任何错误。但这会减慢我的过程,实际上,这等于我没有使用线程的输出。
我收到的错误如下:
Cannot rename /indexes/Segments.new to /indexes/Segments
the file is used by some other process.
任何人都可以帮我解决这个问题吗?
答案 0 :(得分:0)
IndexWriter不是线程安全的,所以这是不可能的。
如果要使用多个线程进行下载,则需要构建一些单线程的“消息泵”,您可以将要下载和创建的文档提供给它,并将它们放入队列中。< / p>
示例,在您的AddDocument方法中,不要直接使用索引,只需将它们发送到最终将索引它的服务。
该服务应该尝试始终为队列中的所有内容编制索引,如果它暂时没有队列,请暂停一段时间。
答案 1 :(得分:0)
您可以采用的方法是为每个线程创建一个单独的索引,并在最后将它们全部合并。例如index1,index2 ... indexn(对应于线程1..n)并合并它们。