1
Public done As New List(Of String)
Public thinkingofdoing As New List(Of String)
Public todo As New List(Of String)

done.AddRange(System.IO.File.ReadAllLines("C:\Users\Work\Desktop\done.txt"))
thinkingofdoing.AddRange(System.IO.File.ReadAllLines("C:\Users\Work\Desktop\thinkingofdoing.txt"))

For i = 0 To thinkingofdoing.Count - 1
    ThreadPool.QueueUserWorkItem(AddressOf caldiff, thinkingofdoing(i))
Next

Public Sub caldiff(ByVal tobedone)
    If done.Contains(tobedone) = False Then
        todo.Add(tobedone)
    End If
End Sub

done.txtthinkingofdoing.txt有 500 万到 800 万行

这需要很长时间 :(,即使四核 AMD 965 超频到 4.2 GHZ。

4

3 回答 3

2

首先,上面的代码无效。 List(Of T)不是线程安全的,因此从多个线程执行此操作实际上会在没有同步的情况下导致重大问题,因为从多个线程调用的调用Add本身Contains并不安全。

更好的选择是选择更好的集合,例如HashSet(Of T),这将导致检查速度更快。我会推荐类似的东西:

public Done as New HashSet(Of String)
public ThinkingOfDoing as IList(Of String) 
public Todo as New List(Of String)

ThinkingOfDoing = System.IO.File.ReadAllLines("C:\Users\Work\Desktop\thinkingofdoing.txt")
Done.AddRange(System.IO.File.ReadAllLines("C:\Users\Work\Desktop\done.txt"))

ToDo = ThinkingOfDoing.Where(Function(i) Done.Contains(i) = False).ToList()

通过使用 a HashSet(Of T)Contains()检查将变得更快(O(1)而不是O(n)),这将导致它运行得更快,甚至是单线程。

如果您不需要存储Done,则可以保留数组并Enumerable.Except直接使用(在内部使用 Set):

ThinkingOfDoing = System.IO.File.ReadAllLines("C:\Users\Work\Desktop\thinkingofdoing.txt")
Dim done = System.IO.File.ReadAllLines("C:\Users\Work\Desktop\done.txt")

Dim Todo = ThinkingOfDoing.Except(done).ToList();
于 2012-07-17T16:11:39.197 回答
0

您可以使用Enumerable.Exceptwhich 应该更有效,因为它实现为HashSet<T>

IEnumerable(Of String) newLines = thinkingofdoing.Except(done)

您还应该使用File.ReadLines而不是,File.ReadAllLines因为前者使用流,而后者一次将所有内容加载到内存中。

我会在不ThreadPool先使用的情况下测试性能。

于 2012-07-17T16:11:44.427 回答
0

这个怎么样 ...

Public done As ISet(Of String) 
Public toDo As New List(Of String)(); 

done = New HashSet(Of String) _
    (System.IO.File.ReadAllLine("C:\Users\Work\Desktop\done.txt")

Using reader As New StreamReader(New FileStream _
        ("C:\Users\Work\Desktop\thinkingofdoing.txt"), FileMode.Open)
    Do While reader.Peek() >= 0
        Dim line = reader.ReadLine()
        If Not done.Contains(line) Then
            toDo.Add(line)
        EndIf
    Loop
End Using

这会将所有已完成的行加载到具有出色查找性能的 HashSet 中,然后不是将执行文件的整个想法加载到内存中,而是逐行解析,并且仅在尚未完成时才添加到 todo 中。

如果 VB.Net 有一个收益回报,我会把它放在一个函数中并在 IEnumerable 上完成 ToList,但是嘿嘿。

于 2012-07-17T16:27:55.077 回答