1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

VB .net BackgroundWorker

Discussão em 'Programação' iniciada por AlmaMater, 6 de Agosto de 2009. (Respostas: 6; Visualizações: 1557)

  1. AlmaMater

    AlmaMater Power Member

    Hello,

    Com o objectivo de obter todo o conteúdo de uma directoria tenho 2 SUBs recursivos o WorkWithDirectory e o WorkWithFilesInDir:

    Código:
    Private Sub ListaFicheiros()
            Dim nameOfDirectory As String
            CLB.Items.Clear() ' CheckListBox
                
             nameOfDirectory = Label1.Text 
          
            Dim myDirectory As DirectoryInfo
            myDirectory = New DirectoryInfo(nameOfDirectory)
            [COLOR="Blue"]WorkWithDirectory(myDirectory)[/COLOR]
        End Sub
    
        Private Sub WorkWithDirectory(ByVal aDir As DirectoryInfo)
             Dim nextDir As DirectoryInfo
            [COLOR="blue"]WorkWithFilesInDir[/COLOR](aDir)
            For Each nextDir In aDir.GetDirectories
                WorkWithDirectory(nextDir)
            Next
        End Sub
    
        Private Sub WorkWithFilesInDir(ByVal aDir As DirectoryInfo)
                 Dim aFile As FileInfo
            For Each aFile In aDir.GetFiles()
                If CLB.Items.Contains(aFile.Name) = True Then
                    Else
                    CLB.Items.Add(aFile.Name)
                End If
            Next
            End Sub
    Acontece que qdo adiciono uma pasta com milhares de ficheiros o programa fica bloqueado até concluir o For Each.. estava a tentar adicionar um BackgroundWorker para fazer isto à parte mas dá-em sempre erro devido à variável "aDir"...

    tentei substituir a parte do "WorkWithFilesInDir" por um BackgroundWorker:

    ficou tudo assim:

    Código:
    Private Sub backgroundWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles backgroundWorker.DoWork
            Dim aFile As FileInfo
            For Each aFile In aDir.GetFiles()
                If CLB.Items.Contains(aFile.Name) = True Then
                Else
                    CLB.Items.Add(aFile.Name)
                End If
            Next
        End Sub

    mas dá o erro de "Error 1 - Name 'aDir' is not declared"

    Alguma ideia? :)

    Thanks
     
  2. Assim nunca ia funcionar. Tem que ser uma função recursiva.
    Código:
        Private Function GetRecursiveDir(ByVal strPath As String) As Integer
            Dim objDir As New DirectoryInfo(strPath & "\")
    
            For Each d In objDir.GetDirectories
                ListBox1.Items.Add(d.FullName)
                GetRecursiveDir(strPath & "\" & d.Name)
                ListBox1.Items.Add("-")
            Next
    
            Dim objFile As FileInfo
            For Each objFile In objDir.GetFiles
                ListBox1.Items.Add(objFile.Name + " - " + Math.Round(objFile.Length / 1024).ToString())
            Next
            Return 0
        End Function
    
    Podes chamar isto de qualquer lado da forma: GetRecursiveDir("C:\temp\")

    A função recursiva chama-se a si própria cada vez que encontra uma nova directoria. Desta forma, só existe um local onde a directoria é processada. Assim que termina essa directoria, a função termina no local anterior e processa o file/dir seguinte.
     
    Última edição pelo moderador: 7 de Outubro de 2009
  3. AlmaMater

    AlmaMater Power Member

    Vou testar.. mas sim, parece que tem muita lógica ;)
     
  4. AlmaMater

    AlmaMater Power Member

    Bem muito obrigado! Já adaptei e funciona muito bem :)

    agora tenho outra dúvida e não sei se tenho de fazer com "delegate" ou não..

    queria fazer a mesma coisa com outro backgroundworker mas para este processo:

    Código:
       Dim I As Integer
            For I = 0 To ListBox1.Items.Count - 1
                ListBox1.SetSelected(I, True)
                ListBox1.SetItemChecked(I, True)
                If ListBox2.Items.Contains(ListBox1.SelectedItem.ToString) = True Then
                           Else
                    ListBox2.Items.Add(ListBox1.SelectedItem.ToString)
                End If
            Next
    isto basicamente passa os Items todos de uma ListBox1 para a ListBox2.. meti esse código todo no backgroundworker e deu erro de :

    "Cross-thread operation not valid: Control 'ListBox1' accessed from a thread other than the thread it was created on."

    Tenho solução para isto? senão fica assim pq o raio dos backgroundworker já me gastaram imenso tempo! :eek:
     
  5. AlmaMater

    AlmaMater Power Member

    Bom..

    Estive aqui a inventar mas não funciona bem..


    Criei o seguinte:
    Código:
    Delegate Function ListBoxCheck() As String
    Código:
    Function ListBoxVerifica() As String
     Dim I As Integer
            For I = 0 To ListBox1.Items.Count - 1
                ListBox1.SetSelected(I, True)
                ListBox1.SetItemChecked(I, True)
                If ListBox2.Items.Contains(ListBox1.SelectedItem.ToString) = True Then
                           Else
    		 Return Microsoft.VisualBasic.Left(ListBox1.SelectedItem.ToString, 1)               
                End If
          Next
    End Function
    e Para adicionar o item devolvido na ListBox2

    Código:
    Private Delegate Sub DelListItem(ByVal sNome As String)
        Private Sub AddListItem(ByVal sNome As String)
            If ListBox2.InvokeRequired Then
                ListBox2.Invoke(New DelListItem(AddressOf AddListItem), sNome)
            Else
                ListBox2.Items.Add(sNome)
            End If
        End Sub
    dentro do backgroundworker coloquei:

    Código:
    Dim NomeItem As string
    NomeItem = ListBox2.Invoke(New ListBoxCheck(AddressOf ListBoxVerifica))
    AddListItem(NomeItem)
     
  6. AlmaMater

    AlmaMater Power Member

    alguém tem alguma ideia? para passar os Items todos da ListBox1 para a ListBox2.. com o BackGrndWorkeer..
     
  7. iznougud

    iznougud I quit My Job for Folding

    Código:
    Private Delegate Sub AdicionaElemento_del(ByVal sNome As String, ByVal lista as ListBox)
    
        Private Sub AdicionaElemento(ByVal sNome As String, ByVal lista as ListBox)
            If not lista.InvokeRequired Then
                lista.Items.Add(sNome)
            End If
        End Sub
    
    Deste modo podes usar qualquer ListBox que tenhas. Agora convém fazeres um que te faça o SetChecked também. Basicamente tudo que involva alterares controlos tens de ter um delegate para isso
     

Partilhar esta Página