" For Each"循环:Vb.net中的应用程序冻结

时间:2015-10-19 20:47:33

标签: vb.net loops foreach

我使用以下代码来获取目录中文件的大小 并将其放入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或解决此问题的解决方案?

3 个答案:

答案 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