dtSearch是全球领先的文本检索工具。dtSearch产品系列包括:dtSearch EnginedtSearch Web with SpidedtSearch DesktopdtSearch NetworkdtSearch Publish接下来我就单独介绍一下dtSearch产品家族里面运用的比较的多的dtSearch Engine在线程的优势。

dtSearch非常易于使用,但如果你看到搜索占用长时间,又阻塞UI线程怎么办呢?很简单,只要运行在另一个线程搜索!我们来看看是如何工作的,以及它如何与UI进行交互。

第一部分,我仔细看的搜索和索引系统dtSearch,我介绍了入门和操作的基本原则。虽然主要结论显然是因为这是一个很容易使用的系统,总会有关于如何做事稍微更复杂的方式考虑。

在这篇文章中,我们就来看看如何应对大搜索和各种各样的事情,你可以用你发现了什么事情。假设你已经有了dtSearch设置和索引可以搜索。如果你不知道怎么做这些事情,然后看看 入门dtSearch。

大搜索

我们探讨最简单的方法来实现,在搜索以前的文章(如果这是没有意义的话请务必先阅读):

SearchJob SJob1 =新SearchJob(); 
SJob1。IndexesToSearch。新增(
                     @“ C:\路径索引 “); 。SJob1 BooleanConditions =“您好,世界”; SJob1.Execute();

这种方法唯一的问题是,它会阻止你不做任何计划其他的事情,直到搜索完毕-这是罚款,只要这不是一个很长的时间。您可以限制通过设置搜索设置的时间属性,它只是停止了指定的秒数后搜索。你也可以限制使用返回的文件的数目MaxFilesToRetrieve属性。

但是,即使你限制要执行仍有正被在UI线程上执行搜索的问题,工作的总量,虽然它是怎么回事没有别的可能发生。标准解决问题的方法是运行的工作量,无论是什么,在另一个线程。dtSearch使得这通过提供一种很容易ExecuteInThread()方法,该方法开始一个新的线程搜索。请注意,如果没有这一点,你就必须去创建和管理线程的麻烦。继调用ExecuteInThread搜索开始一个新的线程中运行,并在UI线程继续的道路上畅通无阻。换句话说,你叫ExecuteInThread并返回imediately但是搜索仍在进行中,结果还没有准备好为你处理呢。

这是一件好事,因为现在在UI线程能够获得与管理的用户界面和响应事件等,但它提出了如何检测时,搜索结果中准备的问题吗?该解决方案是使用任一IsThreadDone或IsThreadDoneWait方法。如果搜索完成,否则为false的第一个返回true。真正的第二个返回后如搜索完成,但然后等待指定的毫秒数,如果它不是返回false之前。

这听起来很容易,我们所有需要做的就是改变标准代码有点:

。SJob1 ExecuteInThread();
(!SJob1.IsThreadDone()),而
{
}

我们的想法是,我们开始去搜索,然后坐在一个“紧”循环等待它完成。

这是行不通的。

释放UI线程

如果您尝试了这一点,你会发现,UI被冻结的时间,搜索是怎么回事,因此也使用一个单独的线程没有收获。问题是,当一个独立的线程是用于搜索在UI线程只是不停地忙碌着等着吧!

你可能会认为,改变循环

。SJob1 ExecuteInThread();
(!SJob1.IsThreadDoneWait(100)),而
{
}

会工作,但没有。原因是完全一样的 - 在UI线程仍在不停地忙碌着,而搜索是怎么回事。

如果您使用的是Windows窗体解决问题的一种方法是拨打的DoEvents使UI线程可以处理任何事件和更新用户界面。

。SJob1 ExecuteInThread();
(!SJob1.IsThreadDoneWait(10)),而
{ 。应用的DoEvents(); }
 

这工作,但很多程序员不喜欢使用的DoEvents。其原因在于它是不可重入。想象一下,有一个事件处理程序也有一个的DoEvents命令。如果此事件被处理为第一的结果会发生什么的DoEvents?在实际应用中的DoEvents不是那么糟糕,因为许多人声称-只要你限制了它的使用每个应用程序之一。

一个更好的方法以释放用户界面和一个用WPF和表格的工作原理是使用一个定时器来检查每隔一段时间即完成搜索。所以,假设有一个Timer对象提供你会做这样的事情:

SJob1。ExecuteInThread();
 timer1.Interval = 100;
timer1.Enabled = TRUE;
回报;
}

此时启动搜索程序终止,并在UI线程可以自由地做自己有。计时器事件处理程序来处理搜索结果:

私人无效timer1_Tick(              对象发件人,EventArgs的五) { 如果(SJob1!IsThreadDone())回报; timer1.Enabled = FALSE; 做一些与结果。




 

这工作和高效率的,但有些程序员不喜欢使用一个定时器来实现的的想法异步处理策略。还存在另一种,这是不复杂得多。

状态更新

有一个与搜索的结果,因为它们得到的工作更有组织和全面的方式。该SearchJob对象具有StatusHandler可以设置为一个对象,它具有一组被称为搜索进展的方法属性。利用这一点,你可以处理的文件,因为它们被发现,你可以通过不占用UI线程保持用户界面响应。

首先,我们需要一个合适的状态处理的对象。这可以实现任何目的ISearchStatusHandler或ISearchStatusHandler2接口。该ISearchStausHandler2接口是一样的ISearchStatusHandler与另外一个方法- OnProgressUpdate -所以我们不妨探讨这个verison的接口。

要使用状态的机制,你首先需要定义一个类继承自ISearchStatusHandler2,你也不妨使用自动生成的选项(右键单击接口名称)来填充类存根的方法:

类SearchStatus:ISearchStatusHandler2
 { 公共无效OnProgressUpdate(                 SearchProgressInfo资讯){   抛出新NotImplementedException(); } 公共AbortValue CheckForAbort() {   抛出新NotImplementedException(); } 公共无效OnFound(                  SearchResultsItem项目){   抛出新NotImplementedException(); } 公共无效OnSearchingFile(                        字符串文件名 ​​) {   抛出新NotImplementedException(); } 公共无效OnSearchingIndex(                            字符串索引){   抛出新NotImplementedException(); } } 

所有你需要做的就是旁边填写您希望使用该方法的细节。你还必须删除NotImplementedException从一些你不想使用的。其实一个好的开始就全部更换了的抛出新的NotImplementedException通过回归除了陈述CheckForAbort方法,该方法返回一个:

AbortValue。继续
 AbortValue.Cancel AbortValue。CancelImmediately

你可以用它来 ​​检查用户是否点击了中止按钮,停止搜索acordingly。

现在只用替换的方法:

公共AbortValue  CheckForAbort()
 { 返回AbortValue。继续; }

当每一种方法被称为是他们的名字很明显,你不必使用任何你不需要的。让我们来看看我们如何能够利用ProgressUpdate方法来保持用户通报有关情况。让我们来简单地显示所执行的更新类型:

公共无效OnProgressUpdate(
                  SearchProgressInfo资讯)
{ 控制台。的WriteLine(资讯。UPDATETYPE); }

现在我们所要做的就是创建我们的类的实例,并开始搜索:

SearchStatus  SStatus =新SearchStatus(); 
。SJob1 StatusHandler = SStatus ;
 SJob1.Execute();

现在开始搜索和OnProgressUpdate称为它的进展。请注意,在这种情况下,我们使用的是UI线程来运行搜索,并在控制台上打印出结果。

如果你想使反馈更加人性化,你可以传递一个进度条由更新OnProgressUpdate方法。首先,我们需要修改的构造函数:

私人进度 _PB;
公共SearchStatus(进度PB)
{
_PB = PB;
}

然后OnProgressUpdate方法:

公共无效OnProgressUpdate
          (SearchProgressInfo资讯)
 {  _PB。PerformStep();如果(_PB.Value> = _PB.Maximum)              _PB.Value = _PB.Minimum; }


现在,如果你运行相同的程序,你会看到进度条的更新,因为搜索进度。

SearchStatus  SStatus =
          新SearchStatus(progressBar1)。SJob1 StatusHandler = SStatus ; SJob1.Execute();

跨线程

有一个小问题就在这里。我们仍然占用UI线程。这将是更好地使用ExecuteInThread运行在另一个线程搜索。然而,这导致了另外一个小问题-跨线程。

如果保留OnProgressUpdate方法不变,只是使用

SJob1。ExecuteInThread();

该方案将一个错误消息崩溃

跨线程操作无效:控制“progressBar1”从一个线程比创建的其他线程访问。

的问题是,所有的状态的对象的方法的一个用于检索和.NET强制只有创建的UI控制线程可以访问它的规则的线程上被运行。

该问题的解决方案听起来更复杂比它。所有我们要做的是使用控件的调用方法来运行使用创建即在此情况下,UI线程控制线程的方法。

使用Invoke方法一般是由需要创建一个委托复杂,但在C#4,这是很容易,因为我们可以使用lambda表达式。因此,为了使新版本的工作中,我们简单地改变OnProgressUpdate阅读:

公共无效OnProgressUpdate(
                   SearchProgressInfo资讯)
{
  _PB.Invoke(新的Action(()=>
     {        _PB。PerformStep();        如果(_PB.Value> = _PB.Maximum)                 _PB.Value = _PB.Minimum;      }   )); }




invoke方法运行,更新的代码进度条原来的UI线程上。

你可以处理类似的跨线程问题使用同一种技术和解耦UI线程搜索线程,因此藏在心里响应和用户的控制之下 - 这是什么使一个很好的应用。

建筑周围dtSearch的应用程序也是你做的搜索结果是什么的问题。你可以处理这些,因为它们使用的是同样类型的这篇文章中讨论的技术生产的。再有,我们甚至还没有触及到许多其他特性 - CDsearch,网络搜索和设置网络蜘蛛的名字只有三个,但这些都是其他的故事。

原文引用http://www.i-programmer.info/programming/database/2887-going-further-with-dtsearch.html?start=1