我使用以下代码来获取目录中文件的大小
并将其放入Label1
:
For Each foundFile As String In My.Computer.FileSystem.GetFiles( _
"\windows",Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly,_
"*.*")
Dim filesizelabel As System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(foundFile)
Label1.Text = Label1.Text + filesizelabel.Length
Next
问题是我的每个循环(系统清理应用程序)超过50个。
当我运行循环时,我的应用程序会冻结,直到循环结束,即使我运行了一个循环。
是否有解决方案使其显示当前文件的名称?我也尝试了这个,但它也冻结了我的应用程序:
label2.text = foundfile
应用程序不响应任何单击,直到完成循环。它显示Label1
中的大小和Label2
中的最后扫描文件。这也冻结了应用程序:
system.threading.thread.sleep(100)
是否有替代foreach或解决此问题的解决方案?
答案 0 :(得分:2)
这是一个使用Async / Await和Button Click()处理程序的简单示例:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.Enabled = False
Await Task.Run(Sub()
' this runs in a different thread without blocking the GUI:
For Each foundFile As String In My.Computer.FileSystem.GetFiles(
"\windows", Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly, "*.*")
Dim filesizelabel As System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(foundFile)
' when you need to update the GUI:
Me.Invoke(Sub()
' ... do it in here ...
Label1.Text = Label1.Text + filesizelabel.Length
End Sub)
Next
End Sub)
Button1.Enabled = True
End Sub
对于VB.Net 2010,请尝试以下方法:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.Enabled = False
Dim T As New System.Threading.Thread(AddressOf Worker)
T.Start()
End Sub
Private Sub Worker()
' this runs in a different thread without blocking the GUI:
For Each foundFile As String In My.Computer.FileSystem.GetFiles(
"\windows", Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly, "*.*")
Dim filesizelabel As System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(foundFile)
' when you need to update the GUI:
Me.Invoke(Sub()
' ... do it in here ...
Label1.Text = Label1.Text + filesizelabel.Length
End Sub)
Next
Me.Invoke(Sub()
Button1.Enabled = True
End Sub)
End Sub
答案 1 :(得分:1)
这是background worker的主要候选人。
阅读有关它们如何工作的内容,但是在高级别上,该任务在另一个线程中运行,其中包含您在主UI线程中访问的一些事件。
Private bw As BackgroundWorker = New BackgroundWorker
Private Sub buttonStart_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
If Not bw.IsBusy = True Then
' this will start the work
bw.RunWorkerAsync()
End If
End Sub
Private Sub buttonCancel_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
If bw.WorkerSupportsCancellation = True Then
' this will allow the user to cancel the work part way through
bw.CancelAsync()
End If
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
' your slow code goes here
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
' you can update the UI here to show progress
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
' your 'I've finished notification' code goes here
End Sub
答案 2 :(得分:0)
Derek 写了一个错误的代码,它不起作用,空闲的头脑代码在 .NET 2.0 上不起作用
如果代码完整,Dereks 方法有效,如下所示:
Private bw As BackgroundWorker = New BackgroundWorker
Private Sub app_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
..
End sub
Private Sub Btn_Click(sender As Object, e As EventArgs) Handles Btn.Click
If Not bw.IsBusy = True Then
' this will start the work
bw.RunWorkerAsync()
End If
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
'your work to not freeze form
end sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
' you can update the UI here to show progress
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
' your 'I've finished notification' code goes here
End Sub