VB.NET 2008应用程序在执行循环期间崩溃

问题描述:

我正在编写一个应用程序,用于将listbox1上的每个项目与listbox2上的所有项目进行比较。如果找到该项目,则将其从两个列表中删除。我们的目标是只让那些未找到的项目保留在这两个列表中。VB.NET 2008应用程序在执行循环期间崩溃

问题是,应用程序只是挂起,我从来没有得到任何结果。我多次查看我的代码,我无法弄清楚发生了什么事(编程noob我知道...)。

有人可以帮我吗?

代码段:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 

    Dim a As String 
    Dim b As String 
    Dim y As String 

    For i As Integer = 0 To ListBox1.Items.Count - 1 
     a = ListBox1.Items(i) 
     y = 1 
     Do While y = 1 
      For x As Integer = 0 To ListBox2.Items.Count - 1 
       b = ListBox2.Items(x) 
       Dim res As Int16 = String.Compare(a, b) 
       If res = 0 Then 
        y = 0 
        ListBox2.Items.Remove(i) 
        ListBox2.Items.Remove(x) 
       ElseIf x = ListBox1.Items.Count Then 
        Exit Do 
       End If 
      Next 
     Loop 
    Next 
End Sub 
+0

如果任何一个列表框在列表框中有模糊怎么办? LB1 = ABCA,LB2 = zBCDEFz。结果应该是什么?见测试代码。 – dbasnett 2010-06-05 12:14:33

如果ListBox1.Items.Count更是ListBox2.Items.Count - 1,X绝不等于ListBox1.Items.Count,所以使用Exit Do将永远运行,代码只会无限循环的

Do While y = 1 

你有没有考虑使用LINQ例如,为了便于列表管理?

编辑:此外,从列表中删除您正在遍历的项目(这对于For Each来说完全是非法的)是错误的,因为每次删除都会偏移循环计数器。

EDIT2:下面是完成任务的一个LINQ片段:

Dim itemsFirst = (From item As String In ListBox1.Items Select item) 
    Dim itemsSecond = (From item As String In ListBox2.Items Select item) 

    Dim dupes = System.Linq.Enumerable.Intersect(itemsFirst, itemsSecond).ToList 
    For Each item In dupes 
     ListBox1.Items.Remove(item) 
     ListBox2.Items.Remove(item) 
    Next item 

是什么呢基本上是提取两个列表中的字符串(因为ListBox.Items集合是一个有点古怪,这是必要的)

之后,我们运行交集方法并将结果复制到列表中。 (.ToList部分) 复制是一个必需的部分,否则愚蠢只会是ListBox的Items的一个子集,我们再次试图通过拉动我们的鞋带来提升自己。

最后一部分只是一个简单的删除循环,即从集合中删除的项目

+0

我浏览过,并遇到此页http://msdn.microsoft.com/en-us/netframework/aa904594.aspx LINQ是一个可下载的加载项? – 2010-06-04 20:26:34

+0

不是,它更像是一种简化数据管理的语言功能。它可以从VS2008向上 – SWeko 2010-06-04 20:37:22

+0

添加了一个基于LINQ的解决方案,基本上是Joel Coehoorn解决方案的修改和解释版本 – SWeko 2010-06-04 20:51:59

你有

ElseIf x = ListBox1.Items.Count Then 
    Exit Do 

当它应该是

ElseIf x = ListBox1.Items.Count - 1 Then 
    Exit Do 

,因为你的循环将更改X进行计数,然后退出而不重复该值。

不仅如此,但为什么有一个Do循环呢?有没有必要继续迭代相同的内部列表框寻找重复,是吗?

第三,你不应该删除的东西,而你通过它们迭代。在你的情况下,for循环正在重用count,所以它是“安全的”,但remove操作将重新索引事物,所以当你删除时,你应该从你的i和x迭代器中减1,这样下一个就不会被重新索引。

再次想到,也许你把那个Do循环放在那里,以覆盖前一次跳过的元素,正如我的第三点所述。

+0

我试过了,但问题仍然存在。我明白你的意思是x计数的变化。是的,我把Do循环放在那里,所以它实际上每次都覆盖整个索引(性能没什么问题,列表只有2500行。) – 2010-06-04 20:28:03

如果您使用Visual Studio 2008或更高版本:

Dim dupes = Listbox1.Items.Cast(Of String)().Intersect(Listbox2.Items.Cast(Of String)()).ToArray() 
For Each item As String in dupes 
    Listbox1.Items.Remove(item) 
    Listbox2.Items.Remove(item) 
Next item 
+0

不幸的是我只能访问Visual Basic 2008 Express版,所以我想这就是为什么我看不到这个功能。 – 2010-06-04 20:25:51

+0

@RedHaze应该处理这个很好。尽管如此,您还是需要一个Imports System.Linq。 – 2010-06-04 20:27:54

+0

谢谢你的耐心等待!我在顶部添加了导入,但仍然收到:'Intersect'不是System.Windows.Forms.ListBox.ObjectCollection' – 2010-06-04 20:29:54

我跑了三种不同的方法进行测试。他们是乔尔斯,斯科和我的。我正在做这个测试性能,但是我发现结果不一样,的列表框不一样。这是我用来测试的代码,所以你可以成为裁判。可能是我的一些愚蠢的错误。

Dim stpw As New Stopwatch 

Private Sub Button1_Click(ByVal sender As System.Object, _ 
          ByVal e As System.EventArgs) Handles Button1.Click 
    Debug.WriteLine("") 
    loadLBTD() ''#load test data 

    doSTPW("Test 1 Start", False) ''#mine 
    ''#get rid of dupes <<<<<<<<<<<<<< 
    Dim dupeL As New List(Of String) 
    For x As Integer = ListBox1.Items.Count - 1 To 0 Step -1 
     If ListBox2.Items.Contains(ListBox1.Items(x)) Then 
      dupeL.Add(ListBox1.Items(x)) 
      ListBox1.Items.RemoveAt(x) 
     End If 
    Next 
    For Each s As String In dupeL 
     ListBox2.Items.Remove(s) 
    Next 
    doSTPW("Test 1 End") 

    loadLBTD() ''#load test data 

    doSTPW("Test 2 Start", False) ''#sweko 
    ''#get rid of dupes <<<<<<<<<<<<<< 
    ''#I had to set Option Strict to Off to get this to work <<<<<<< 
    Dim itemsFirst = (From item As String In ListBox1.Items Select item) 
    Dim itemsSecond = (From item As String In ListBox2.Items Select item) 

    Dim dupes = System.Linq.Enumerable.Intersect(itemsFirst, itemsSecond).ToList 
    For Each item In dupes 
     ListBox1.Items.Remove(item) 
     ListBox2.Items.Remove(item) 
    Next item 
    doSTPW("Test 2 End") 

    loadLBTD() ''#load test data 

    doSTPW("Test 3 Start", False) ''#joel 
    ''#get rid of dupes <<<<<<<<<<<<<< 
    Dim dupes2 = ListBox1.Items.Cast(Of String)().Intersect(ListBox2.Items.Cast(Of String)()).ToArray() 
    For Each item As String In dupes2 
     ListBox1.Items.Remove(item) 
     ListBox2.Items.Remove(item) 
    Next item 
    doSTPW("Test 3 End") 
End Sub 

Private Sub doSTPW(ByVal someText As String, Optional ByVal showTM As Boolean = True) 
    stpw.Stop() ''#stop the clock 
    If flip Then Debug.Write("'T ") Else Debug.Write("'F ") 
    Debug.Write("LBCnts " & ListBox1.Items.Count & " " & ListBox2.Items.Count) 
    Dim s As String 
    If showTM Then 
     s = String.Format(" {0} {1}", someText, stpw.ElapsedTicks.ToString("N0")) 
    Else 
     s = String.Format(" {0}", someText) 
    End If 
    Debug.WriteLine(s) 
    stpw.Reset() ''#reset and start clock 
    stpw.Start() 
End Sub 

Dim flip As Boolean = False 
Private Sub loadLBTD() 
    ''#Create test data 
    Dim tl1() As String = New String() {"A", "X", "y", "z", "B", "w", "X", "y", "z"} 
    Dim tl2() As String = New String() {"A", "y", "z", "Q", "A", "y", "z", "Q", "A", "y", "z", "Q"} 
    ListBox1.Items.Clear() 
    ListBox2.Items.Clear() 
    ''#load listboxes 
    If flip Then 
     ListBox1.Items.AddRange(tl2) 
     ListBox2.Items.AddRange(tl1) 
    Else 
     ListBox1.Items.AddRange(tl1) 
     ListBox2.Items.AddRange(tl2) 
    End If 
    ''#end of test data setup 
End Sub 

此外,正如所料,LINQ更简洁但更慢。如果代码很少使用,则无关紧要。我对LINQ和Eratosthenes筛选有过不好的经验。

+0

我认为我的速度会比较慢,因为我猜的是Cast的调用类型()。至于linq,如果使用正确,它可以非常快,但你必须小心。任何时候你发现自己调用.ToList()或.ToArray()都会导致性能下降。在这种情况下,有必要避免潜在的竞争条件。 – 2010-06-05 14:09:32

+0

@Joel Coehoorn - 结果有什么不同?这只是我,但我从来没有见过LINQ在这种事情上更快的情况。 – dbasnett 2010-06-05 14:13:34

+0

你是对的。该代码将每月使用两次,总数低于10,000条的设置数据。我用3000左右的记录进行的测试花费了大约3秒钟,这确实比他们使用的老方法(手动比较)要好。我并没有期待你们有这么多的帮助,反馈一直都很惊人。非常感谢你。 – 2010-06-06 14:53:46