我有一个WPF程序,它抓取某个网络目录中的所有目录,并在列表视图中列出它们。
问题是目录太多,列表加载最多可能需要5秒钟。
我想知道是否有办法通过更高效的代码加快速度。或者甚至可能是一种将列表存储在数组中的方法,只是在第一次之后每次查找更改?
For Each i As String In Directory.GetDirectories(dir)
If File.Exists(Path.GetFullPath(i) & "\cover.jpg") Then
If (File.GetAttributes(Path.GetFullPath(i)) And FileAttributes.Hidden) <> FileAttributes.Hidden Then
Dim foldername As String = Path.GetFileName(i)
Dim moviename As String = foldername
If moviename.Length > 4 Then
If moviename.Substring(0, 4) = "The " Then
moviename = moviename.Remove(0, 4)
End If
End If
Dim display As Boolean = True
If IO.Directory.GetDirectories(Path.GetFullPath(i)).Length < 1 Then
If IO.Directory.GetFiles(Path.GetFullPath(i), "*.avi").Length < 1 Then
If IO.Directory.GetFiles(Path.GetFullPath(i), "*.mp4").Length < 1 Then
If IO.Directory.GetFiles(Path.GetFullPath(i), "*.mkv").Length < 1 Then
display = False
End If
End If
End If
End If
If display = True Then
Showslist.Items.Add(New With {Key .img = Path.GetFullPath(i) & "\cover.jpg", .name = foldername, .path = Path.GetFullPath(i), .created = Directory.GetCreationTime(Path.GetFullPath(i)), .moviename = moviename})
End If
End If
End If
Next
答案 0 :(得分:2)
<强> 1。不要多次读取目录的内容。而是,读取所有必需的内容并将其缓存在(内存中)变量中。这将有助于提高性能,因为访问内存比执行I / O要快得多(此处:访问文件系统)。例如:
If IO.Directory.GetFiles(…, "*.avi").Length < 1 Then If IO.Directory.GetFiles(…, "*.mp4").Length < 1 Then If IO.Directory.GetFiles(…, "*.mkv").Length < 1 Then …
您刚刚查询了同一个目录三次。您可以将其更改为仅读取一次内容(因此可能会将代码加速三次),然后在内存中对其进行过滤:
'Imports System.IO
'Imports System.Linq
' access the file system only once and store the results in-memory…
Dim filePaths As String() = Directory.GetFiles(…, "*")
' … and perform everything else on that in-memory cache:
If Not filePaths.Any(Function(fp) Path.GetExtension(fp) = ".avi") Then
If Not filePaths.Any(…) Then
If Not filePaths.Any(…) Then
…
PS:也许值得指出的是,与
Directory.GetFiles
不同,System.IO.Path
方法不会导致昂贵的文件系统命中:它们只是对字符串进行操作已知包含文件系统路径。
<强> 2。请考虑递归地读取根目录的完整内容。 Directory.GetFiles
方法有一个重载Directory.GetFiles(String, String, SearchOption)
,其SearchOption
参数可以设置为SearchOption.AllDirectories
。在这种情况下,您不仅可以从指定目录本身获取内容,还可以从其所有子目录中获取内容。
这意味着,您需要一次调用Directory.GetFiles
(对于根目录)而不是多次调用,这意味着您将再次减少昂贵的I / O调用次数。将结果存储在一个数组中,然后从那里开始构建WPF列表。
' read the contents of the network root directory, including all of its sub-directories…
Dim filePaths As String() = Directory.GetFiles(…, "*", SearchOption.AllDirectories)
' …and do everything else using the in-memory cache built above:
For Each filePath As String in filePaths
…
Showslist.Items.Add(…)
Next