none
Essa sub funciona apenas fora do Thread por que? RRS feed

  • Pergunta

  • No evento Load eu crio uma classe que tem a seguinte sub que monta uma Treeview no Form1.

    Public Sub AntesLerDiretorioParaOTreeview(ByVal caminho As String)
            Dim Di As New DirectoryInfo(caminho)
    
            'Converte tag do Treeview em seu respectivo caminho.
            dcTreeview.Add(dcTreeview_cont, caminho)
    
            'Adiciona nome e caminho ao Treeview usando LerDiretoriosEArquivosRecursivamenteEAdicionarAaTreeView()
            'form1.Invoke(New Action(Function() Form1.tvPastas.Nodes.Add(Di.Name)))
    
            Form1.tvPastas.Nodes.Add(Di.Name)
    
            Form1.tvPastas.Nodes.Item(contador_pastas_principais_colocadas).Tag() = dcTreeview_cont
    
            'Cria a ordem dos grupos
            CriaOrdemDosGrupos(caminho, dcTreeview_cont)
    
            dcTreeview_cont += 1
    
            LerDiretoriosRecursivamenteEAdicionarAaTreeView(caminho, Form1.tvPastas.Nodes(contador_pastas_principais_colocadas))
            contador_pastas_principais_colocadas += 1
        End Sub

    O problema é que se eu executar esse código fora de uma Thread funciona normal, mas se eu usar uma Thread ele da erro na parte:

     Form1.tvPastas.Nodes.Add(Di.Name)

    Ela simplesmente não executa fazendo que a parte :

    Form1.tvPastas.Nodes.Item(contador_pastas_principais_colocadas).Tag() = dcTreeview_cont

    Dê erro index out of range.

    Edit:

    1- esse botão está no form1 e chama a Sub AntesLerDiretorioParaOTreeview que está em uma classe.

    Public Sub TsButtonAdicionarPasta_Click(sender As Object, e As EventArgs) Handles TsButtonAdicionarPasta.Click Dim Fd As New FolderBrowserDialog With { .ShowNewFolderButton = False } Fd.ShowDialog() 'Verifica se o usuario selecionou um caminho e se já esta salvo o caminho If Fd.SelectedPath = Nothing OrElse salva_caminhos_treeview.IndexOf(Fd.SelectedPath) <> -1 Then Exit Sub End If 'Salva Pastas colocadas no Treeview para a Proxima seção. salva_caminhos_treeview.Add(Fd.SelectedPath) 'coloca na lista que sera utilizada para salvar as configuraçoes apos fechar o programa. My.Settings.caminho.Clear() For Each itens As String In salva_caminhos_treeview My.Settings.caminho.Add(itens) Next 'inicia Tread que vai montar o Treeview Dim td1 As Threading.Thread td1 = New Threading.Thread(Sub() funcoes.AntesLerDiretorioParaOTreeview(Fd.SelectedPath)) With { .Name = "Thread Treeviel" } td1.Start()

    End sub

    AntesLerDiretorioParaOTreeview:

     Public Sub AntesLerDiretorioParaOTreeview(ByVal caminho As String)
            Dim Di As New DirectoryInfo(caminho)
    
            'Converte tag do Treeview em seu respectivo caminho.
            dcTreeview.Add(dcTreeview_cont, caminho)
    
            'Adiciona nome e caminho ao Treeview usando LerDiretoriosEArquivosRecursivamenteEAdicionarAaTreeView()
            Form1.Invoke(New Action(Function() Form1.tvPastas.Nodes.Add(Di.Name)))
    
            Form1.tvPastas.Nodes.Item(contador_pastas_principais_colocadas).Tag() = dcTreeview_cont
    
            'Cria a ordem dos grupos
            CriaOrdemDosGrupos(caminho, dcTreeview_cont)
    
            dcTreeview_cont += 1
    
            LerDiretoriosRecursivamenteEAdicionarAaTreeView(caminho, Form1.tvPastas.Nodes(contador_pastas_principais_colocadas))
            contador_pastas_principais_colocadas += 1
        End Sub


    Essa sub  AntesLerDiretorioParaOTreeview() popula um Treeview(tvPastas) que está no Form1. A outra parte dela é essa: 

    Private Sub LerDiretoriosRecursivamenteEAdicionarAaTreeView(ByVal diretorio As String, ByVal noPai As TreeNode)
            'Adiciona dados do AntesLerDiretorioParaOTreeview e monta o treeview
            Dim dirsFilhos() As String = System.IO.Directory.GetDirectories(diretorio)
            If dirsFilhos.Length = 0 Then
                Return
            Else
                For Each dirFilho In dirsFilhos
                    If FileIO.FileSystem.GetFiles(dirFilho, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 1 Then
                        Try
                            If FileIO.FileSystem.GetFiles(dirFilho, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 0 Then
                                Dim Di As New DirectoryInfo(dirFilho)
    
                                'Converte tag do Treeview em seu respectivo caminho.
                                dcTreeview.Add(dcTreeview_cont, dirFilho)
    
                                'Cria a ordem dos grupos
                                CriaOrdemDosGrupos(dirFilho, dcTreeview_cont)
    
                                'Adiciona node
                                Dim noFilho As TreeNode = New TreeNode(Di.Name) With {
                                        .Tag = dcTreeview_cont
                                    }
    
                                Form1.tvPastas.Invoke(New Action(Function() noPai.Nodes.Add(noFilho)))
    
                                dcTreeview_cont += 1
                                LerDiretoriosRecursivamenteEAdicionarAaTreeView(dirFilho, noFilho)
                            End If
                        Finally
                        End Try
                    ElseIf FileIO.FileSystem.GetDirectories(dirFilho, FileIO.SearchOption.SearchTopLevelOnly).Count > 0 Then 'pega pastas que tem outras pastas dentro com 1 arquivo de video só
                        For Each files In FileIO.FileSystem.GetDirectories(dirFilho, FileIO.SearchOption.SearchAllSubDirectories)
                            If FileIO.FileSystem.GetFiles(files, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 0 Then
                                Try
                                    If FileIO.FileSystem.GetFiles(dirFilho, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 0 Then
                                        Dim Di As New DirectoryInfo(dirFilho)
    
                                        'Converte tag do Treeview em seu respectivo caminho.
                                        dcTreeview.Add(dcTreeview_cont, dirFilho)
    
                                        'Cria ordem dos grupos.
                                        CriaOrdemDosGrupos(dirFilho, dcTreeview_cont)
    
                                        'Adiciona node
                                        Dim noFilho As TreeNode = New TreeNode(Di.Name) With {
                                                .Tag = dcTreeview_cont
                                            }
    
                                        Form1.tvPastas.Invoke(New Action(Function() noPai.Nodes.Add(noFilho)))
    
                                        dcTreeview_cont += 1
                                        LerDiretoriosRecursivamenteEAdicionarAaTreeView(dirFilho, noFilho)
                                    End If
                                Finally
                                End Try
                                Exit For
                            End If
                        Next
                    End If
                Next
            End If
        End Sub


    Essa ultima parte: LerDiretoriosRecursivamenteEAdicionarAaTreeView está na mesma classe e também modifica o mesmo  Treeview no Form1.

    Ela funciona se não usar Thread (no evento load ela é usada 2x sem Thread) , mas se usar, ou ela não é executada ou da o erro: System.InvalidOperationException: 'Invoke or BeginInvoke cannot be called on a control until the window handle has been created.'.

    Edite: 

    Form:

    Imports System.IO
    
    
    Public Class Form1
        '# Variaveis
    
        Dim caminho_path As String = Application.StartupPath & "\Thumb"
        Dim salva_caminhos_treeview As New List(Of String) 'para salvar ao fechar o programa
        Dim funcoes As Funcoes
    
        '# Load / Close
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            funcoes = New Funcoes
        End Sub
    
    
    
    
    
    
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim Fd As New FolderBrowserDialog With {
                          .ShowNewFolderButton = False
                      }
            Fd.ShowDialog()
    
            'Verifica se o usuario selecionou um caminho e se já esta salvo o caminho
            If Fd.SelectedPath = Nothing OrElse salva_caminhos_treeview.IndexOf(Fd.SelectedPath) <> -1 Then
                Exit Sub
            End If
    
            'Salva Pastas colocadas no Treeview para a Proxima seção.
            salva_caminhos_treeview.Add(Fd.SelectedPath) 'coloca na lista que sera utilizada para salvar as configuraçoes apos fechar o programa.
            My.Settings.caminho.Clear()
            For Each itens As String In salva_caminhos_treeview
                My.Settings.caminho.Add(itens)
            Next
    
            'inicia Tread que vai montar o Treeview
            Dim td1 As Threading.Thread
            td1 = New Threading.Thread(Sub() funcoes.AntesLerDiretorioParaOTreeview(Fd.SelectedPath)) With {
                .Name = "Thread Treeviel"
            }
            td1.Start()
    
            td1.Join()
        End Sub
    End Class

    Classe: 

    Imports System.IO
    Public Class Funcoes
        '# Variaveis
        Dim contador_pastas_principais_colocadas = 0
        Dim dcTreeview_cont As Integer = 0
    
        Dim dcTreeview As New Dictionary(Of Integer, String)
    
    
    
        '# Sub
    
        Public Sub AntesLerDiretorioParaOTreeview(ByVal caminho As String)
            Dim Di As New DirectoryInfo(caminho)
    
            'Converte tag do Treeview em seu respectivo caminho.
            dcTreeview.Add(dcTreeview_cont, caminho)
    
            'Adiciona nome e caminho ao Treeview usando LerDiretoriosEArquivosRecursivamenteEAdicionarAaTreeView()
            Form1.Invoke(New Action(Function() Form1.tvPastas.Nodes.Add(Di.Name)))
    
            Form1.tvPastas.Nodes.Item(contador_pastas_principais_colocadas).Tag() = dcTreeview_cont
    
            dcTreeview_cont += 1
    
            LerDiretoriosRecursivamenteEAdicionarAaTreeView(caminho, Form1.tvPastas.Nodes(contador_pastas_principais_colocadas))
            contador_pastas_principais_colocadas += 1
        End Sub
    
        Private Sub LerDiretoriosRecursivamenteEAdicionarAaTreeView(ByVal diretorio As String, ByVal noPai As TreeNode)
            'Adiciona dados do AntesLerDiretorioParaOTreeview e monta o treeview
            Dim dirsFilhos() As String = System.IO.Directory.GetDirectories(diretorio)
            If dirsFilhos.Length = 0 Then
                Return
            Else
                For Each dirFilho In dirsFilhos
                    If FileIO.FileSystem.GetFiles(dirFilho, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 1 Then
                        Try
                            If FileIO.FileSystem.GetFiles(dirFilho, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 0 Then
                                Dim Di As New DirectoryInfo(dirFilho)
    
                                'Converte tag do Treeview em seu respectivo caminho.
                                dcTreeview.Add(dcTreeview_cont, dirFilho)
    
    
    
                                'Adiciona node
                                Dim noFilho As TreeNode = New TreeNode(Di.Name) With {
                                        .Tag = dcTreeview_cont
                                    }
    
                                Form1.tvPastas.Invoke(New Action(Function() noPai.Nodes.Add(noFilho)))
    
                                dcTreeview_cont += 1
                                LerDiretoriosRecursivamenteEAdicionarAaTreeView(dirFilho, noFilho)
                            End If
                        Finally
                        End Try
                    ElseIf FileIO.FileSystem.GetDirectories(dirFilho, FileIO.SearchOption.SearchTopLevelOnly).Count > 0 Then 'pega pastas que tem outras pastas dentro com 1 arquivo de video só
                        For Each files In FileIO.FileSystem.GetDirectories(dirFilho, FileIO.SearchOption.SearchAllSubDirectories)
                            If FileIO.FileSystem.GetFiles(files, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 0 Then
                                Try
                                    If FileIO.FileSystem.GetFiles(dirFilho, FileIO.SearchOption.SearchAllSubDirectories, "*.mp4", "*.avi", "*.wmv", "*.mkv").Count > 0 Then
                                        Dim Di As New DirectoryInfo(dirFilho)
    
                                        'Converte tag do Treeview em seu respectivo caminho.
                                        dcTreeview.Add(dcTreeview_cont, dirFilho)
    
    
    
                                        'Adiciona node
                                        Dim noFilho As TreeNode = New TreeNode(Di.Name) With {
                                                .Tag = dcTreeview_cont
                                            }
    
                                        Form1.tvPastas.Invoke(New Action(Function() noPai.Nodes.Add(noFilho)))
    
                                        dcTreeview_cont += 1
                                        LerDiretoriosRecursivamenteEAdicionarAaTreeView(dirFilho, noFilho)
                                    End If
                                Finally
                                End Try
                                Exit For
                            End If
                        Next
                    End If
                Next
            End If
        End Sub
    End Class
    

    Precisa no form1 criar 1 botão e um Treeview com nome tvPastas.

    • Editado _Lucas_-Pedro quinta-feira, 1 de novembro de 2018 02:00
    terça-feira, 30 de outubro de 2018 23:31

Respostas

  • Aqui amigo, tens que cria uma variavel form.

    Aqui eu crio a new class e indico o form

    Aqui uma theread mais bem feita com STA

    E a variavel form

    Sem o erro de invoke, espero ter ajudado.

    • Marcado como Resposta _Lucas_-Pedro quinta-feira, 1 de novembro de 2018 15:11
    quinta-feira, 1 de novembro de 2018 03:57

Todas as Respostas