AN?LISE MULTITHREAD .NET

DS2T 13/12/2015 17:53:15
#455086
Fala pessoal, beleza?

Então, estou tentando me aprofundar um pouco com processos paralelos em .NET. Já tive experiência com thread, mas um colega meu fez um programa e eu tentei reproduzir.
Ele usa 190 threads rodando em paralelo realizando determinada operação e a UI não trava. O meu programa, depois da oitava thread já começa a travar a UI. Fazendo com o scrollbar fique lento, a atualização do listview fique lento também.
Inicialmente pensei que pudesse ser algo do próprio Listview. Porque eu tava precisando forçar o Redraw com o método update para atualizar o desenho. Mas meu amigo disse que isso é problema de acesso da thread. Uma deve estar bloqueando a outra.

Tentei usando Mutex, tentei usando Monitor... e nada, mesmo resultado.
Agora estou criando um módulo de Logs criando arquivo .txt para cada thread e vendo como está sendo o acesso. Só que é algo ruim de analisar.

Minha pergunta é: Existe alguma ferramenta no VS que facilite a percepção do que está acontecendo no ambiente multithread? Porque debugar é tenso demais.

Valeu galera!
GUIMORAES 15/12/2015 13:27:34
#455182
Trabalhar com threads não é fácil, principalmente em WindowForms.
A questão é, você está atualizando sua listview de qual forma?
Você está utilizando Delegate para isto?
Você está verificando se o objeto necessita de uma invocação (InvokeRequired)?
OCELOT 15/12/2015 14:41:14
#455189
Resposta escolhida
Desconheço qualquer coisa que poderia te ajudar a debugar isso, mas uma coisa eu digo, ninguém usa 190 threads.

Primeiro de tudo, o máximo de threads que vão executar realmente em paralelo é determinado por quantos cores seu computador possui, então se tem por exemplo 4 cores no máximo 4 threads vão executar ao mesmo tempo, mais que isso eles vão dividir o tempo da CPU.

Uma coisa muito importante é que Thread não deve de forma alguma modificar a UI, apenas a Thread que criou a UI deve fazer isso, qualquer outra se precisar modificar a UI deve, no caso do Windows Forms, usar o Invoke, porém fazer isso o tempo todo torna praticamente inútil o uso de Threads, então você deve usar isso o mínimo o possível.

Não é qualquer coisa que vai ter ganho de performance com o uso de threads, por exemplo se você usar várias threads para acessar arquivos em um HD mecânico você provavelmente vai ter uma perda de performance.

O uso de Monitor, Mutex ou algo do tipo serve para sincronizar várias threads, por exemplo quando você precisa acessar um mesmo recurso de várias threads porém este recurso não pode ser acessado ao mesmo tempo por mais de 1 thread, nestes casos você pode usar estes objetos para garantir que apenas uma thread acesse ele de cada vez, mas o uso incorreto deles pode causar um deadlock (thread 1 esperando thread 2 terminar algo e, ao mesmo tempo, thread 2 esperando a thread 1 terminar algo).


De resto não tem como dizer o que você deve fazer, você não disse nada do que faz, apenas disse que tinha problemas com threads.
DS2T 28/12/2015 10:09:50
#455572
Vamos lá, primeiro gostaria de agradecer a atenção de vocês. Segundo, gostaria de pedir desculpa pelo tópico [Ô]esquecido[Ô]. Tive alguns problemas que me impediram de dar a devida a atenção . Espero que relevem dessa vez hahaha
Realmente, não me atentei à detalhes cruciais para me ajudarem na resolução do problema.

O problema consiste basicamente em:
A cada [Ô]t[Ô] segundos, um número de [Ô]n[Ô] threads executará um bloco de operações de processamento que estarão assinalados numa Fila. Cada thread terá uma respectiva fila o qual será adicionadas objetos Mensagem, que serão processadas dentro da thread.

Elas executam esse método:

Private Sub MetodoExecuta(ByVal index As Integer)
While threadsRodando(index)
waitsHandles(index).WaitOne()[ô]Espera até ter dados na fila
If estadosProcessamento(index) = enumEstadoProcessamento.Ociosa Then[ô]Verifico se ela está ociosa para processar os próximos dados
If filas(index).Count > 0 Then[ô]Se tiver itens na fila
MudaEstado(index, enumEstadoProcessamento.Processando)
While (filas(index).Count > 0) [ô]Enquanto houver dados na fila
Dim msg As IProcess = filas(index).Dequeue()
ProcessarMensagem(msg)[ô]Processa a mensagem
RaiseEvent MensagemProcessada(index, msg.Processar())[ô]Aqui eu chamo o evento da classe para poder atualizar a UI.
End While
MudaEstado(index, enumEstadoProcessamento.Ociosa)
End If
End If
End While
End Sub



Repare que logo no começo eu adiciono um waitsHandles(index).WaitOne(). Isso acontece, porque criei um array (para cada thread) de EventWaitHandle. Por que isso?
Porque eu quero que a Thread permaneça ociosa até ser adicionado algum dado à Fila.

No método onde eu adiciono itens as respectivas filas das threads, eu chamo o método :

waitsHandles(index).Set()

Para assim liberar a thread para continuar rodando. Como o uso de EventWaitHandle é meio desconhecido pra mim, acredito que talvez o problema da lentidão esteja aí. Não sei. Apesar de achar que não faz muito sentido, pois pelo que li na documentação. Apenas deixa a thread ociosa até eu usar o Set.

Enfim, a partir de que o evento MensagemProcessada é disparado, no form eu faço assim:

 Private Delegate Sub MensagemProcessada(index As Integer, mensagem As ExpressaoEntity)

Private Sub gerenciador_MensagemProcessada(index As Integer, mensagem As Object)
Dim metodo As New MensagemProcessada(AddressOf SubMensagemProcessada)
AcessaControleSeguro(MeuListView1, metodo, index, mensagem)
End Sub

Private Sub AcessaControleSeguro(controle As Control, metodo As [Delegate], ParamArray parametros() As Object)
If controle.InvokeRequired Then
controle.BeginInvoke(metodo, parametros)
Else
metodo.DynamicInvoke(parametros)
End If
End Sub




Agradeço a todos pelas respostas já ditas!
E se alguém puder me ajudar mais nessa, fico feliz também =]
Tópico encerrado , respostas não são mais permitidas