VB.net事件处理程序在再次触发时中止

时间:2014-02-05 15:52:48

标签: vb.net linq events search flowlayoutpanel

我有一个用VB.net编写的应用程序。在该应用程序中,我有多种形式和许多功能。应用程序开始的形式是某种菜单。在后台,我有一个菜单项列表,用户可以看到并用于打开新表单。可以通过文本框搜索所有这些菜单项,您可以在其中填写一些文本,然后代码将所有菜单项名称与填写的文本进行比较并显示结果。此事件在此文本框的每个textchanged事件上触发。但是,如果用户输入的名称很多(例如,大约100次),则视图需要一些时间(3到5秒)才能显示所有这些结果。现在我想知道是否可以在再次调用同一事件时中止第一个事件处理程序。这意味着,如果我在文本框中输入,并且对于前4或5个字母,几乎所有菜单项都是匹配项,那么我想中止该搜索并立即开始新的搜索。有没有办法检测到同一事件再次被调用并中止当前事件以使新事件立即开始?

提前感谢您阅读本文并帮助我解决此问题!

3 个答案:

答案 0 :(得分:0)

尝试添加条件。在搜索方法中,如果文本长度超过某个值,请再次调用相同的事件(如递归方法)。它应该有用。

此致

丹尼尔

答案 1 :(得分:0)

在搜索字符串的长度上添加一些条件...就像它的长度应该是5或更多

OR一次显示的最大结果应该是有限的。

答案 2 :(得分:0)

为了实现这一目标,您将不得不在一个单独的线程中完成工作。主要原因是WinForms是单线程的。 WinForm中的所有UI相关事件都在同一UI线程上处理。因此,当您仍在处理上一个事件时,TextChanged事件无法再次触发。如果完成处理,UI将被锁定,直到第一个事件。

但是,如果您在另一个线程中执行所有菜单过滤工作,那么您的UI将被释放,以便在您完成工作时对用户输入做出反应。然后,在前一个事件处理完毕之前,您的TextChanged事件将被允许触发。

在WinForm项目中实现多线程的最简单方法是使用BackgroundWorker组件。您可以在表单设计器工具框中找到它。幸运的是,BackgroundWorker组件具有一些属性和方法,可用于实现您所描述的取消。

例如,这是一个非常简单的例子。在此示例中,每次TextBox中的文本发生更改时,它都会BackgroundWorker1执行一些工作。它所做的工作就是等待两秒钟,然后将TextBox1的内容复制到TextBox2。如果文本在这两秒完成之前再次更改,它将取消bacground工作并从头开始再次启动。

Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
    If BackgroundWorker1.IsBusy Then
        BackgroundWorker1.CancelAsync()
    Else
        BackgroundWorker1.RunWorkerAsync()
    End If
End Sub

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    For i As Integer = 1 To 20
        If BackgroundWorker1.CancellationPending Then
            e.Cancel = True
            Exit Sub
        End If
        Thread.Sleep(100)
    Next
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    If e.Cancelled Then
        BackgroundWorker1.RunWorkerAsync()
    Else
        TextBox2.Text = TextBox1.Text
    End If
End Sub

为了使上述示例有效,BackgroundWorker1.WorkerSupportsCancellation属性必须设置为True

正如您所看到的,当文本发生更改时,它只会检查IsBusy属性,该属性确定后台线程是否仍在使用上一个事件。如果是,则取消它。如果不是,则启动它。

需要在单独线程上完成的所有工作都在后台worker DoWork事件处理程序中完成。在进行工作时,需要定期检查是否已取消。如果它已被取消,它需要停止正在进行的操作并设置事件args的Cancel属性以指示它正在停止,因为它已被取消。

完成后台工作后(无论是通过取消还是完成其任务),后台工作人员会引发RunWorkerCompleted事件。该事件的事件参数具有Cancelled属性,该属性指示工作是否已完成,因为它已过早取消。在示例中,如果它被取消,它只是从头开始重新开始工作。

对于它的价值,如果你有一些方法可以将菜单过滤算法加速到接近瞬间的程度,那么所有这些都没有实际意义。可以通过将菜单编入suffix array

之类的索引来实现