我有一个列表视图,列出目录中的所有项目,如下所示:
但正如您在此图片中所见:
它们不按顺序排列,因为已完全跳过一个图像文本,但图像本身仍处于有序状态。
但是,当它从列表中进一步下降时,从大约一半开始,它们开始变得完全混淆,如下例所示:
单击图像时,它会在右侧显示正确图像的预览。
这是我用来加载所有图片的代码:
Dim imgList As New ImageList
Dim imgSize As New Size
Dim count As Integer = 0
Dim imgFilename As String
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'Dim imlTemp As New ImageList
Dim dirFiles() As String = IO.Directory.GetFiles(My.Settings.GalleryLocation)
'Dim item As New ListViewItem
For Each dirFile As String In dirFiles
imgFileName = IO.Path.GetFileName(dirFile)
Dim img As New System.Drawing.Bitmap(dirFile)
Dim imgImage As Image = Image.FromFile(dirFile)
'Dim imgHeight As Integer
'imgHeight = imgImage.Height
imgSize.Width = 120
imgSize.Height = 174
Threading.Thread.Sleep(10)
BackgroundWorker1.ReportProgress(100 / ((dirFiles.Count + 1) - count), img)
Next
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ListView1.SmallImageList = imgList
ListView1.LargeImageList = imgList
imgList.ImageSize = imgSize
imgList.ColorDepth = ColorDepth.Depth32Bit
ListView1.Items.Add(imgFilename, count)
imgList.Images.Add(e.UserState.Clone)
count += 1
'ListView1.EnsureVisible(ListView1.Items.Count - 1)
End Sub
在我添加到后台工作程序之前,它有大量图像的加载时间,因此我认为我实现了后台工作程序以允许完成异步工作。但是,在任务开始时有些事情是完全错误的,并且在列表中多次出现错误,如图3所示,它完全混乱。
是否有人知道出了什么问题,或者我想要做的任何其他解决方案?
答案 0 :(得分:1)
由于ReportProgress()
没有阻塞(据我所知),文件的迭代速度可能比UI更新的速度快。
要保持同步,您应该创建一个包含要更新的所有内容的自定义类,并将其传递给ReportProgress()
方法(甚至自动执行一些步骤)。
例如:
Public Class GalleryImage
Public Property FullPath As String
Public Property FileName As String
Public Property [Image] As Image
Public Sub New(ByVal File As String)
Me.Image = Image.FromFile(File) 'Get the image.
Me.FullPath = File 'Save the full path of the image.
Me.FileName = Path.GetFileName(File) 'Get the file name.
End Sub
End Class
(另外,如果您想要文件名而不是扩展程序,则可以使用Path.GetFileNameWithoutExtension()
)
现在你的代码。首先,counter
变量并不是必需的,因为它可以被ListView1.Items.Count
或imgList.Images.Count
替换。
其次,您不应该经常设置imgSize
变量或ListView的Small-
/ LargeImageList
属性。这样做是完全没必要的,会减慢速度。对于ListView,只需设置一次图像列表,对于imgSize
变量,您可以这样做:
Dim ReadOnly imgSize As New Size(120, 174)
使变量ReadOnly
完成它听起来的样子;你可以从中读取,但不能修改它。
现在要解决其他问题,我们将从BackgroundWorker的For Each
循环开始:
For Each dirFile As String In dirFiles
Threading.Thread.Sleep(10) 'You don't need this Sleep if you don't want to.
'Report the progress, declare an in-line version of our class and send it with.
BackgroundWorker1.ReportProgress(100 / ((dirFiles.Count + 1) - ListView1.Items.Count), New GalleryImage(dirFile)) 'A new GalleryImage is created. The property setting is handled by the class itself.
Next
如您所见,我们现在已经将代码缩小了很多。
现在我们将处理ReportProgess()
事件:
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Dim img As GalleryImage = e.UserState 'Retrieve our class, no need to clone it.
imgList.Images.Add(img.Image) 'Add the image first (I don't know for sure, but if you add the image after, wouldn't it require to redraw the ListView an extra time?).
ListView1.Items.Add(img.FileName, imgList.Images.Count - 1) 'Add the new item with the values from our class.
End Sub
最后,填充的初始化和初始设置应该在例如Form Load
事件中完成:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'In here we do all the standard settings and initializations.
ListView1.SmallImageList = imgList
ListView1.LargeImageList = imgList
imgList.ImageSize = imgSize
imgList.ColorDepth = ColorDepth.Depth32Bit
End Sub
由此我认为我应该已经涵盖了所有内容。
希望这有帮助!