THREAD PROBLEMA

FLEFLE 25/03/2013 22:55:53
#421041
Fala galera,

Seguinte estou com um pequeno grande problema....

Estou usando uma Thread para buscar dados do banco de dados sem travar o form....

Jogo o Resultado em um DataGridView, porem a ScrollBar do DataGridWiew Some, desaparece, se oculta ou qualquer outra coisa.....

Como que faço para que isso não ocorra!!!
NILSONTRES 25/03/2013 23:26:19
#421042
Isso ocorreu comigo, eu desabilitava ao iniciar a operação, e habilitava depois, sabe o que eu fiz ?
Parei de desabilitar, isso porque não descobri a causa.
ALEVALE 26/03/2013 08:20:38
#421043
O que eu acho que você vai ter que fazer é criar outra thread para dar um enable no scrollbar já tentou ? ? ?
OCELOT 26/03/2013 09:35:49
#421046
Meio difícil descobrir no chute o que pode estar acontecendo sem nenhum código para ver.

Uma dúvida, você faz a busca em uma thread e nela mesmo você modifica o DataGrid? Se sim esse pode ser o problema já que o acesso a métodos ou propriedades de controles fora da thread em que foram criados não garante o funcionamento correto dos controles.
FLEFLE 26/03/2013 11:59:04
#421060
Deu muito Futuro Não os meus teste... Vou postar um exemplo de como que to fazendo:

Função que inicia a thread:

[txt-color=#0000f0]Privat Sub[/txt-color] Inicia_Thread()

[txt-color=#0000f0]Control[/txt-color].CheckForIllegalCrossThreadCalls = [txt-color=#0000f0]False[/txt-color]
Var_THR_Busca = [txt-color=#0000f0]New Thread[/txt-color]([txt-color=#0000f0]AddressOf[/txt-color] Busca_dados)
Var_THR_Busca.Start()

[txt-color=#0000f0]End Sub[/txt-color]


[txt-color=#0000f0]Privat Sub[/txt-color] Busca_dados()

[ô]Preenche os Dados
DataGridView_Registro.Rows.Add([txt-color=#e80000][Ô]False[Ô][/txt-color], _
[txt-color=#e80000][Ô]Dado 1[Ô][/txt-color], _
[txt-color=#e80000][Ô]Dado 2[Ô][/txt-color])

[txt-color=#0000f0]End Sub[/txt-color]

So que a ScrollBar do DataGrid não aparece....

Se eu adicionar sem usar a Thread a ScrollBar aparece normalmente!!!
OCELOT 26/03/2013 14:01:44
#421069
Você não deve modificar nenhum controle dentro de outra thread pois pode acontecer coisas inesperadas. Esse é um dos maiores erros que as pessoas cometem ao usar Threads

Nunca mude o CheckForIllegalCrossThreadCalls, ele serve apenas para ajudar a debugar o programa, se setando ele como false faz algum erro não acontecer isso significa que você tem um erro no programa, na verdade essa propriedade é por padrão True apenas quando debugando o programa, pois ajuda a encontrar problemas, rodando o programa fora do Visual Studio ela já é false por padrão.

O correto ao se usar threads é fazer todo o trabalho que não precisa fazer nada com a interface, como por exemplo carregar um DataSet, e depois de carregado o DataSet você pode usar ele como DataSource do Grid, porém você deve fazer isso não nessa Thread e sim na Thread principal, que é a que criou o Form, para isso você usa o Invoke do objeto Control, segue um pequeno exemplo

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ThreadPool.QueueUserWorkItem(AddressOf CarregarDados)
End Sub

Private Sub CarregarDados(ByVal state As Object)
Dim cnn As New SqlConnection([Ô]Server=.\SQLEXPRESS;Database=MeuBancoDeDados;Trusted_Connection=True[Ô])
cnn.Open()

Dim cmd As New SqlCommand([Ô]SELECT * FROM MinhaTabela[Ô], cnn)
Dim adapter As New SqlDataAdapter(cmd)
Dim dados As New DataSet
adapter.Fill(dados)

[ô]Aqui se usa o Invoke que faz com que o código seja executado na thread principal
Invoke(Sub(d) DataGridView1.DataSource = d, dados.Tables(0))

cnn.Close()
cnn.Dispose()
adapter.Dispose()
cmd.Dispose()
End Sub


Se eu tirar o Invoke ali e usar direto [ô]DataGridView1.DataSource = dados.Tables(0)[ô] acontece o que você fala de dar problema na barra de rolagem, com essa linha não acontece nenhum problema

Repare também que em vez de criar manualmente a Thread eu usei o ThreadPool.QueueUserWorkerItem para criar a Thread para mim, não tem muita diferença entre os dois quando se trata de apenas uma Tread, mas se tiver várias Threads usando o ThreadPool ele cria uma fila delas e executa uma certa quantidade de Threads de cada vez, mas no geral eu acho apenas mais prático usar o ThreadPool, e na verdade existem outras formas de se usar threads no .Net
FLEFLE 26/03/2013 16:11:16
#421076
Perfeito o problema das ScrollBars foi resolvido, mas apareceu outro...

Usando seu exemplo ele cria colunas novas, como que eu faço para ele preencher as colunas já existentes...

Pois tem algumas colunas que são ocultas, e o Head delas ficam igual a do banco de dados e aparecer isso pro cliente não é legal!!!


que eu faço agora???
OCELOT 26/03/2013 17:32:36
#421081
Se você já criou as colunas manualmente e definiu o nome do campo do banco de dados na propriedade DataPropertyName então coloque em algum lugar, pode ser no Load do Form ou antes de iniciar a thread a seguinte linha

DataGridView1.AutoGenerateColumns = False

Por algum motivo obscuro essa propriedade não aparece na janela de propriedades e tem que ser modificada por código
KERPLUNK 26/03/2013 18:06:03
#421084
O que não dá pra entender é:
1 - Porque achar que criar uma thread vai resolver o problema de preenchimento de grid.
2 - Por que preencher um grid manualmente, linha a linha, quando se pode simplesmente usar um DataReader e um List<T> passando o mesmo como DataSource

Ter Threads para executar tarefas, não torna nada mais rápido. Se você usar OOP e uma thread para preencher um List<T>, isso sim faria diferença de performance...
FLEFLE 26/03/2013 18:18:29
#421085
KERPLUNK não é questão de performance que uso a thread....

A questão é o SERVIDOR fica longe (outro pais) do Computador CLIENTE...

Uso a thread para o FORM não ficar travado e mostrar pro usuário que o processo de busca esta acontecendo... Entendeu!!!!

Teria outra forma de fazer essa busca sem travar o FORM???

Algumas coisas eu ainda estou aprendendo e thread e uma coisa nova pra mim....
No caso o que seria OOP e List<T> ???


------
OCELOT To dando uma olhada na sua dica pra ver o que eu faço!!!!
KERPLUNK 26/03/2013 18:29:07
#421086
OOP = Object Oriented Programming
List<T> = Uma lista de objetos(classes) que descrevem uma fonte de dados, geralmente uma tabela.

Para entender melhor, seria algo assim(pseudo-código)

Retorno = List<MinhaClasse>
AbreConexao => con
ComandoSQL(Select * from tabelaX, con) => cmd
DataReader dr = cmd.ExecuteReader
While dr.HasRows
{
MinhaClasse item = new MinhaClasse()
Thread => PreencherItem(item, DadosDoDataReader)
Adicionar(item => Retorno)
AcionarEvento(LendoDados)
}
AcionarEvento(DadosLidos)
Retornar Retorno


No pseudo-código acima, você abre um DataReader que vai conter o retorno de uma query. Para cada ítem, você aciona uma thread que vai preencher o ítem com os dados do DataReader, para cada linha retornada. Isso vai fazer a leitura ficar muito mais rápida, visto que os ítems serão lidos [Ô]todos ao mesmo tempo[Ô] praticamente. Além disso, com os eventos que são acionados durante a leitura e ao final dela, basta fazer um delegate no seu form para monitorá-las, assim, você pode passar para o usuário que os dados estão sendo lidos e também quando essa leitura terminou.
Página 1 de 2 [15 registro(s)]
Faça seu login para responder