FUNCAO BACKGROUND

ALEVALE 11/09/2012 13:44:31
#409437
Fala pessoal blz ?

Tenho uma função que buscaarquivos, gostaria de executar essa função só que ao mesmo tempo gostaria que ela liberasse o form.
Tenho um listbox no qual irei selecionar os computadores que irei executar essa função após selecionar esses computadores irei abrir um outro form que irá mostrar qual o computador que está sendo executado a busca assim como algumas informações como por exemplo uma progressbar como o andamento.
O problema é que quando eu executo a busca o form com as informações [Ô]fica travado[Ô] pois ele está executando a função de procurar alguém tem alguma sugestão ?
A questão também é que se eu mostrar o form frmPesquisando ele não faz a chamada para a função, abaixo está o exemplo.
Obrigado !

Form:
Dim I As Integer
For I = 0 To ListBoxComputadoresAuditados.Items.Count - 1
frmPesquisando.Show()
Dim list As List(Of String) = FileHelper.GetFilesRecursive([Ô]\\[Ô] & ListBoxComputadoresAuditados.Items(I).ToString & [Ô]\C$[Ô])

frmPesquisando.lblComputadorAtual.Text = ListBoxComputadoresAuditados.Items(I).ToString

For Each path In list
MsgBox(path)
Next
Next


A baixo a clase de procurar
Imports System.IO

[ô][ô][ô] <summary>
[ô][ô][ô] This class contains directory helper method(s).
[ô][ô][ô] </summary>
Public Class FileHelper

[ô][ô][ô] <summary>
[ô][ô][ô] This method starts at the specified directory, and traverses all subdirectories.
[ô][ô][ô] It returns a List of those directories.
[ô][ô][ô] </summary>
Public Shared Function GetFilesRecursive(ByVal initial As String) As List(Of String)
[ô] This list stores the results.
Dim result As New List(Of String)

[ô] This stack stores the directories to process.
Dim stack As New Stack(Of String)

[ô] Add the initial directory
stack.Push(initial)

[ô] Continue processing for each stacked directory
Do While (stack.Count > 0)
[ô] Get top directory string
Dim dir As String = stack.Pop
Try
[ô] Add all immediate file paths
result.AddRange(Directory.GetFiles(dir, [Ô]*.txt*[Ô]))

[ô] Loop through all subdirectories and add them to the stack.
Dim directoryName As String
For Each directoryName In Directory.GetDirectories(dir)
stack.Push(directoryName)
Next

Catch ex As Exception
End Try
Loop

[ô] Return the list
Return result
End Function

End Class
ALEVALE 11/09/2012 13:47:54
#409438
Creio eu que terei que trabalhar com treads correto ?
KERPLUNK 11/09/2012 14:42:52
#409442
O background worker vai servir perfeitamente para o que você quer. Claro que poderia trabalhar com threads puramente, mas complicaria um pouco...
ALEVALE 12/09/2012 08:55:53
#409475
KERPLUNK obrigado pela sugestão !

Dei uma analisada e fiz um projetinho de teste mas não consegui verificar o porque o do form fica em [Ô]freeze[Ô] mesmo assim, poderia dar uma olhada ?
OCELOT 12/09/2012 10:56:40
#409486
Resposta escolhida
O problema ali é que você está abrindo um form de dentro do backgroundworker, o que faz ele ser executado no mesmo thread q a sua função que lista os arquivos, travando assim este form.

O que você deve fazer é mostrar este form da thread principal do seu programa, por exemplo no click do botão antes de você iniciar o backgroundworker, e fechar ele depois que o backgroundworker terminar, lembrando que isso deve ser feito na thread principal.
KERPLUNK 12/09/2012 11:20:24
#409490
Se você precisa colocar um form dentro de um processo separado, o backgroundworker não vai ser aconselhável, nesse caso, use delegates.
ALEVALE 12/09/2012 13:59:59
#409505
Entendi funcionou perfeitamente !

Só mais uma dúvida a chamada eu fiz antes da tread realmente, FORM.SHOW() blz sem erro.

Dentro da tread eu fiz um loop pegando várias computadores, estou percorrendo eles sem erro, a dúvida é eu não consigo atualizar as informações no outro form.
Eu dou um show nele e depois caiu na tread e dentro da tread eu mando atualizar um label só que não muda ele porque ?

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Pesquisando.Show()
atividadeSegundoPlano.RunWorkerAsync()
End Sub

Private Sub executaTrabalho(ByVal processoAtivo As BackgroundWorker)
For i = 0 To cboUsuarios.Items.Count - 1

[ô]ATUALIZO AQUI O LABEL SÓ QUE ELE NÃO ATUALIZA NO FORM.
Pesquisando.lblComputadorAtual.Text = cboUsuarios.Items(i).ToString

Dim list As List(Of String) = FindFiles.GetFilesRecursive([Ô]\\[Ô] & cboUsuarios.Items(i).ToString & [Ô]\C$[Ô])

For Each path In list
Dim strResultado As String = path
MsgBox(path)
Next

Next

End Sub
OCELOT 12/09/2012 15:57:53
#409515
Você não pode modificar forms criados em threads diferentes diretamente, para isso o correto é você fazer com que ele execute esta parte de código na thread do form através do método Invoke do mesmo, por exemplo

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Pesquisando.Show()
atividadeSegundoPlano.RunWorkerAsync()
End Sub

Private Sub executaTrabalho(ByVal processoAtivo As BackgroundWorker)
For i = 0 To cboUsuarios.Items.Count - 1

[ô]ATUALIZO AQUI O LABEL SÓ QUE ELE NÃO ATUALIZA NO FORM.
Me.Invoke(DirectCast(AddressOf AlterarLabel, Action(Of String)), cboUsuarios.Items(i).ToString)

Dim list As List(Of String) = FindFiles.GetFilesRecursive([Ô]\\[Ô] & cboUsuarios.Items(i).ToString & [Ô]\C$[Ô])

For Each path In list
Dim strResultado As String = path
MsgBox(path)
Next

Next

End Sub

Private Sub AlterarLabel(Texto As String)
Pesquisando.lblComputadorAtual.Text = Texto
End Sub


Da para fazer também usando Lambda ou Delegates anônimas, mas não lembro como elas são no VB já que trabalho praticamente só com C#, então no exemplo criei uma Sub nova mesmo

Só que você deve evitar ao máximo fazer isso se forem muitos itens já que ele torna o processo um pouco mais lento, alias, qualquer loop com muitos itens fica muito mais lento se você ficar atualizando um form
Tópico encerrado , respostas não são mais permitidas