c# - 在 ASP.NET MVC 站点中使用 Lucene.Net 时出现目录锁定错误

标签 c# asp.net-mvc lucene locking lucene.net

我正在构建一个 ASP.NET MVC 站点,我想在其中使用 Lucene.Net 进行搜索。我已经构建了一个 SearchController 及其所有方法,但在首次初始化 SearchController 时出现运行时错误。

在 SearchController 中,这是我创建 IndexWriter 的方式:

public static string IndexLocation = HostingEnvironment.MapPath("~/lucene");
public static Lucene.Net.Analysis.Standard.StandardAnalyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer();
public static IndexWriter writer = new IndexWriter(IndexLocation,analyzer);

错误发生在最后一行。这是我收到的消息:

Lucene.Net.Store.LockObtainFailedException: Lock obtain timed out: SimpleFSLock@C:\Users\Username\Desktop\SiteSolution\Site\lucene\write.lock

此外,这是堆栈跟踪:

[LockObtainFailedException: Lock obtain timed out: SimpleFSLock@C:\Users\Username\Desktop\SiteSolution\Site\lucene\write.lock]
   Lucene.Net.Store.Lock.Obtain(Int64 lockWaitTimeout) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Store\Lock.cs:107
   Lucene.Net.Index.IndexWriter.Init(Directory d, Analyzer a, Boolean create, Boolean closeDir, IndexDeletionPolicy deletionPolicy, Boolean autoCommit, Int32 maxFieldLength, IndexingChain indexingChain, IndexCommit commit) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Index\IndexWriter.cs:1827
   Lucene.Net.Index.IndexWriter.Init(Directory d, Analyzer a, Boolean closeDir, IndexDeletionPolicy deletionPolicy, Boolean autoCommit, Int32 maxFieldLength, IndexingChain indexingChain, IndexCommit commit) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Index\IndexWriter.cs:1801
   Lucene.Net.Index.IndexWriter..ctor(String path, Analyzer a) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Index\IndexWriter.cs:1350
   Site.Controllers.SearchController..cctor() in C:\Users\Username\Desktop\SiteSolution\Site\Controllers\SearchController.cs:95

[TypeInitializationException: The type initializer for 'Site.Controllers.SearchController' threw an exception.]

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +86
   System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +230
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +67
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80

[InvalidOperationException: An error occurred when trying to create a controller of type 'Site.Controllers.SearchController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +190
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +68
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +118
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +46
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +63
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +13
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8682818
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

我该如何解决这个问题?

更新:我已经重新开始处理这个特定的项目,但似乎我还没有完全解决这个问题。

真正的问题是 write.lock 文件在索引使用结束后没有被删除。根据我接受的答案,我理解了基本的实现逻辑,但我不确定我是否正确实现了它。以下是我的类(class)中可能无效的其他一些方法:

    public ActionResult Search(string query)
    {

        var reader = writer.GetReader(); // Get reader from writer
        var searcher = new IndexSearcher(reader); // Build IndexSearch

        //Execute search...

        // Dispose of objects
        searcher = null;
        reader = null;

        return View();
    }

    public void AddToIndex(Document doc)
    {
        writer.AddDocument(doc);
        writer.Flush();
        writer.Optimize();
        writer.Flush();
    }

    private bool disposed = false;

    protected override void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Release managed resources.
            }
            try
            {
                writer.Close();
                writer = null;
            }
            catch
            {

            }
            // Release unmanaged resources.
            // Set large fields to null.
            // Call Dispose on your base class.
            disposed = true;
        }
        base.Dispose(disposing);
    }

有什么想法吗?

最佳答案

之所以会出现这种情况是因为writer创建了一个名为write.lock的空文件作为跨进程锁。当该文件存在时,Lucene 假定有人对该目录具有写锁。

当您错误地终止进程时,文件不会被删除。所以Lucene认为还是有人在持有这把锁。这就是为什么您应该始终使用 finally 语句来关闭索引。

如果您确定该文件存在错误(即没有运行 Lucene 进程),则可以删除该文件。但是,您的索引可能处于损坏状态,因为写入显然在中途终止。

关于c# - 在 ASP.NET MVC 站点中使用 Lucene.Net 时出现目录锁定错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4241480/

相关文章:

c# - .NET Core 2.1 API Post Controller 返回无效输入

javascript - SignalR 服务 : Get message depending on user role

java - Apache Solr 快速入门教程 - 加载主类 SimplePostTool 时出错

Solr:对带空格的字符串使用通配符

jquery - 如何正确使用 Html.Raw(Json.Encode(Model)) ?

powershell - Solr 7.3.1 不会启动 "SSL_PORT_PROP"此时是意外的

c# - 在使用 bot 框架时,如何设计 skype for business html 消息的样式?

c# - 异常处理中间件和页面

c# - asp.net c#代码中的错误(mysql数据库连接)

asp.net - 从 ASP.NET MVC 操作发送 HTTP 404 响应的正确方法是什么?