AJUDA COM THREAD

 Tópico anterior Próximo tópico Novo tópico

AJUDA COM THREAD

VB.NET

 Compartilhe  Compartilhe  Compartilhe
#480497 - 28/03/2018 12:25:00

ALEVALE
JUNDIAI
Cadast. em:Março/2012


Pessoal bom dia,

Preciso de uma ajuda com a criação de threads, hoje o meu código está funcionando perfeitamente, porém quero otimizar ele.
Pois basicamente ele le o Active Directory buscando algumas informações em determinadas OU´s.

A questão é que o código é sempre o mesmo o que muda são as OU´s que eu leio, ou seja tenho que ler as OU´s (1,2,3 etc) porém o código executado é o mesmo
contudo claro, só mudo a OU que o sistema irá ler.

Vamos lá....

Tenho essa função que lê as Ou´s e depois adiciono eu uma classe para ler no código mais a fundo.
AD_Active_Sites()

Private Function AD_Active_Sites()
        Try
            Dim SQL_Connection As SqlConnectionStringBuilder
            SQL_Connection = SQL_ConnectionString()
            Dim Site As String = String.Empty
            Dim OU_Users As String = String.Empty
            Dim OU_Groups As String = String.Empty
            Dim OU_Servers As String = String.Empty
            Dim OU_Desktops As String = String.Empty
            Dim OU_Laptops As String = String.Empty
            Dim OU_Person_name As String = String.Empty
            Dim OU_Person_email As String = String.Empty
            Dim OU_Group_email As String = String.Empty
            Dim OU_Group_status As String = String.Empty

            Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection(SQL_Connection.ConnectionString)
            Dim cmd As New System.Data.SqlClient.SqlCommand
            sqlConnection1.Open()
            cmd.Connection = sqlConnection1
            cmd.CommandType = System.Data.CommandType.Text
            cmd.CommandText = "select * from site_settings where ou_status='Active'"
            cmd.ExecuteNonQuery()

            Using sda As New SqlDataAdapter()
                cmd.Connection = sqlConnection1
                sda.SelectCommand = cmd
                Dim dr As SqlDataReader = cmd.ExecuteReader()
                If dr.HasRows Then
                    While dr.Read()
                        'SITE NAME
                        If Not IsDBNull(dr("OU_sync_site_name")) Then
                            Site = dr("OU_sync_site_name")
                        End If

                        'OU USERS
                        If Not IsDBNull(dr("OU_sync_users")) Then
                            OU_Users = dr("OU_sync_users")
                        End If

                        'OU GROUPS
                        If Not IsDBNull(dr("OU_sync_groups")) Then
                            OU_Groups = dr("OU_sync_groups")
                        End If

                        'OU SERVERS
                        If Not IsDBNull(dr("OU_sync_servers")) Then
                            OU_Servers = dr("OU_sync_servers")
                        End If

                        'OU DESKTOS
                        If Not IsDBNull(dr("OU_sync_desktops")) Then
                            OU_Desktops = dr("OU_sync_desktops")
                        End If

                        'OU LAPTOPS
                        If Not IsDBNull(dr("OU_sync_laptops")) Then
                            OU_Laptops = dr("OU_sync_laptops")
                        End If

                        'SITE PERSON NAME
                        If Not IsDBNull(dr("OU_sync_site_contact_name")) Then
                            OU_Person_name = dr("OU_sync_site_contact_name")
                        End If

                        'SITE PERSON CONTACT
                        If Not IsDBNull(dr("OU_sync_site_contact_email")) Then
                            OU_Person_email = dr("OU_sync_site_contact_email")
                        End If

                        'SITE GROUP EMAIL
                        If Not IsDBNull(dr("OU_sync_site_group_email")) Then
                            OU_Group_email = dr("OU_sync_site_group_email")
                        End If

                        'SITE GROUP EMAIL STATUS
                        If Not IsDBNull(dr("OU_site_group_email_status")) Then
                            OU_Group_status = dr("OU_site_group_email_status")
                        End If

                        'ADD
                        Site_Class.Add(New clsSites(Site, OU_Users, OU_Groups, OU_Servers, OU_Desktops, OU_Laptops, OU_Person_name, OU_Person_email, OU_Group_email, OU_Group_status))

                    End While

                End If

            End Using

        'CLOSE
            sqlConnection1.Close()

        Catch ex As Exception
        End Try

    End Function

FORM PRINCIPAL
        Dim Sites = From p In Site_Class Order By p.Site Select p

        For Each Site As clsSites In Sites
        MINHA FUNÇÃO
        Next

Nessa parte do código para executar a (MINHA FUNÇÃO) precisaria executar ela várias vezes ao mesmo tempo por isso pensei nas threads, pois assim consigo realizar a busca no AD em todas as OU´s ao mesmo tempo.

Eu até achei um exemplo:
Dim STthread_Data As thread_Data
        '    STthread_Data.TCPIPAddr = Site.Site
        '    STthread_Data.TCPIPPort = Site.OU_Users

        '    Dim multiThread As Thread = New Thread(AddressOf testthread)
        '    multiThread.SetApartmentState(ApartmentState.MTA)
        '    multiThread.Start(STthread_Data)

    Public Structure thread_Data
        Dim TCPIPAddr As String
        Dim TCPIPPort As String
    End Structure

Private Function testthread(ByVal STthread_Data As thread_Data)
MINHA FUNÇÃO COM PARAMETROS
End function

Mas o que achei estranho foi que ele duplicou os registros após a consulta no AD (Eu adiciono os dados em uma classe).

Alguém poderia me dar uma luz ?

---------------------------------------------------------------
"Já está provado por A+B que A+B num prova nada"
---------------------------------------------------------------

Resposta escolhida #480506 - 28/03/2018 17:21:28

OCELOT
SOROCABA
Cadast. em:Março/2012


Última edição em 28/03/2018 17:22:09 por OCELOT

No geral quando uma pessoa que não tem experiência com Threads fala que precisa usar Thread para algo eu digo ela está errada sem nem ver o que ela quer fazer.

Se quer usar Thread para otimizar algo existe uma grande chance de estar errado, Thread só vai te dar um desempenho maior se o limitador for a CPU, se este processo não faz com que a CPU chegue a 100% então você provavelmente vai ter um ganho muito pequeno, se não nulo, de performance.

O ganho de performance com o uso de Threads é quase nulo quando se trata de operações de IO, como ler arquivos, acessar dados na rede, sejam arquivos, bancos de dados, e muito provavelmente acessar o AD, pois você possui um limite de transmissão de dados que você vai alcançar muito antes de chegar a velocidade máxima que o seu código pode rodar na CPU.

Se quiser ainda assim tentar, eu diria para usar o Task Parallel Library em vez de usar Threads diretamente, é mais fácil de usar e ela cuida da criação de Threads sozinho e você pelo menos vai conseguir verificar se tem algum ganho de velocidade e se seu código vai funcionar rodando em várias Threads, ele ainda vai bloquear a execução do seu código até todas as Threads terminarem de rodar, diferente de se usar Threads diretamente

Em vez de fazer isso
Dim Sites = From p In Site_Class Order By p.Site Select p

For Each Site As clsSites In Sites
    MINHA FUNÇÃO
Next


Use
Dim Sites = From p In Site_Class Order By p.Site Select p

Parallel.ForEach(Sites, Sub (s)
                            'Seu código aqui, "s" é o item atual, cada um deles vai executar em uma thread
                        End Sub)
'Código aqui vai rodar só depois que todas as Threads terminarem





#480510 - 28/03/2018 18:12:37

ALEVALE
JUNDIAI
Cadast. em:Março/2012


Muito obrigado a sua ajuda foi ótima, agradeço os comentários.

Sobre o ganho de performance, terei porque basicamente esse função ela lê a OU do AD e pega algumas informações dos usuários, hoje o código estava lendo OU quando finalizado a leitura ela iria para a próxima OU e executaria a mesma rotina.

Por isso a ideia de usar algo para otimizar a performance.

O código funcionou, a única coisa que está estranho e que no meu outro teste estava acontecendo a mesma coisa é, que os registros estão se perdendo, basicamente após colher as informações do AD eu as insiro no banco de dados.

Só que antes eu as insiro em uma classe, para depois realizar o insert de uma só vez (registro por registro).

Quando estou executando o for each do seu exemplo (no meu também) o sistema está passando certo os parâmetros para a minha função que são basicamente (Nome da OU, LDAP da OU).

Exemplo:
1 - LDAP://OU=1
2 - LDAP//OU=2

Quando eu analise os registros o sistema está se perdendo está inserindo por exemplo o usuário 1 como 2, exemplo:
Registros
1 - Site 1 - Joazinho Silva
2 - Site 2 - Mariazinha
3 - Site 2 - Joazinho Silva.

Se eu executar o mesmo código sem o parallel, os registros são inseridos corretamente, então estou descartando a possibilidade de ser algo na outra função.

Estava pensando e pode será que como o código está sendo executado várias vezes ao mesmo tempo, as variavies que insiro na classe/banco estão se perdendo pois estão sendo atualizadas ao mesmo tempo.

Tem alguma sugestão ?



---------------------------------------------------------------
"Já está provado por A+B que A+B num prova nada"
---------------------------------------------------------------

#480515 - 29/03/2018 08:18:17

OCELOT
SOROCABA
Cadast. em:Março/2012


Se está inserindo errado pode ser problema no como você está fazendo o INSERT, só consigo imaginar que pode ser que você esteja usando variáveis que estão sendo usadas por todas as threads em vez de variáveis locais.

Por acaso você não estaria tentando usar o mesmo SqlConnection e SqlCommand de várias threads?



 Tópico anterior Próximo tópico Novo tópico


Tópico encerrado, respostas não sao permitidas
Encerrado por ALEVALE em 21/04/2018 11:05:08