AJUDA COM BACKGROUND WORKER

KURTGU 24/08/2015 02:47:09
#450397
Pessoal nunca precisei usar o BackGroundWork to tentando fazer algo e nao estou conseguindo....Ultilizando o codigo abaixo preencho um listview com 200 itens, ate ai tudo bem mais a progressbar ao chegar em 101 travar pois o maximun dela esta definido para 100 como faco pra o maximum da progressbar seja o tanto de itens que ira ser adicionado ao listview, e como faco pra ela carregar corretamente pois sempre carrega ate o meio da progressbar e nunca por completo...

Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Control.CheckForIllegalCrossThreadCalls = False
BackgroundWorker1.WorkerReportsProgress = True
End Sub

Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim items = CType(e.Argument, ListViewItem())
For i = 1 To 200
ListView1.Items.Add(i)
BackgroundWorker1.ReportProgress(i, items)
Threading.Thread.Sleep(100)
Next
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles startAsyncButton.Click
BackgroundWorker1.RunWorkerAsync()
End Sub

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

ProgressBar1.Value = e.ProgressPercentage
resultLabel.Text = e.ProgressPercentage & [Ô] %[Ô]
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MsgBox([Ô]CARREGAMENTO COMPLETO[Ô])
End Sub


End Class
TUNUSAT 24/08/2015 07:48:37
#450398
KURTGU,

Você tem que configurar a propriedade [Ô]Maximum[Ô] = número de registros encontrados.

===============================
VB.NET - Usando o componente ProgressBar
http://www.macoratti.net/vbn_pb1.htm
===============================
... classe ProgressBar possui quatro propriedades que são comumente usadas e que não são herdadas do controle ou outra classe base.


[td]Maximum


Propriedade Valor do Tipo Descrição[td]
IntegerO valor máximo do intervalo exibido no controle. O valor padrão é 100 - Read/Write.
MinimumIntegerO valor mínimo do intervalo exibido pelo controle. O valor padrão é 0. Read/Write.
StepIntegerA quantidade pela qual a barra de progresso é incrementada quanto o método PerformStep é chamado. Valor padrão é zero. Read/Write.
ValueIntegerA posição atual da barra de progresso. O valor padrão é zero. Read/Write.

===============================

Veja também:

===============================
Propriedade ProgressBar.Maximum
https://msdn.microsoft.com/pt-br/library/system.windows.forms.progressbar.maximum(v=vs.110).aspx
===============================
Progress Bar exceeding maximum/minimum value in VB.Net 2010?
http://stackoverflow.com/questions/13815045/progress-bar-exceeding-maximum-minimum-value-in-vb-net-2010
===============================
ProgressBar.Maximum : ProgressBar « System.Windows.Forms « VB.Net by API
http://www.java2s.com/Code/VBAPI/System.Windows.Forms/ProgressBarMaximum.htm
===============================

[][ô]s,
Tunusat.
KURTGU 24/08/2015 08:40:54
#450403
Tunusat esse e problema nao estou sabendo aonde adicionar o progressbar.maximun, tentei adicionar dentro do for que vai adicionando no listview mais recebo um erro...
NICKOSOFT 24/08/2015 10:28:24
#450412
vc define fora do background
aqui
BackgroundWorker1.ReportProgress(i, items) vc deveria passar apenas um parâmetro q já seria a porcentagem....como é um laco até 200 poderia ser i/2, usando o padrão do progressbar de 100 como maximo
alterei apenas isso
BackgroundWorker1.ReportProgress(Int(i / 2))
funcionou certinho
KURTGU 24/08/2015 13:24:57
#450423
NickSoft ele continua nao preenchendo a progressbar completamente....
TUNUSAT 24/08/2015 13:50:20
#450424
KURTGU,

Não ... acredito que você tenha que configurar o [Ô]Maximum[Ô] antes de você fazer o [Ô]FOR[Ô].
Por exemplo: O ListViewItem tem uma propriedade Count. Dai você joga o valor para dentro do [Ô]Maximum[Ô] ... algo assim:
dim pb as ProgressBar  
pb.Maximum = ListViewItem.Items.Count


[][ô]s,
Tunusat.

NICKOSOFT 24/08/2015 14:35:56
#450426
aki foi normal....
com o código aparecendo tmb
OCELOT 24/08/2015 14:50:58
#450428
Vocês estão se preocupando com a barra de progresso estar errada e ninguém se preocupou com o verdadeiro erro nesse código.

O progresso estar errado é um mero erro de lógica, por algum motivo você está definindo o valor máximo do ProgressBar para o valor errado, o seu erro real ai é estar preenchendo um ListView dentro de um BackgroundWorker.

Repare nesta linha:
Control.CheckForIllegalCrossThreadCalls = False

O simples fato dela estar em seu código já indica que está fazendo algo errado, você nunca deveria ter que mudar este valor para False, se precisou mudar ele para False para o seu programa funcionar então você fez algo errado.

Uma regra básica para praticamente qualquer interface gráfica de qualquer linguagem em qualquer sistema operacional é de que apenas a Thread que criou a janela pode modificar ela. E devo repetir, isso vale para quase qualquer toolkit de quase todas as linguagens de praticamente todos os sistemas operacionais.

Isso é um erro básico de quem está começando a mexer com threads, a primeira coisa que tentam fazer é uma forma de carregar dados sem travar a UI e em quase todos os casos fazem isso da forma errada.

A forma correta de se usar o BackGroundWorker para carregar dados em uma lista é a de usar o event DoWork apenas para coletar as informações, por exemplo acessando o banco de dados, você então deixaria estas inormações na memória e retornaria estas informações através da propriedade Result do objecto DoWorkEventArgs que foi passado para o evento DoWork, em momento algum dentro do DoWork você deve modificar qualquer controle do formulário.

Quando terminar este valor que foi passado para o Result pode ser pego dentro do evento RunWorkerCompleted, e então é ai que se deve modificar a interface e exibir os resultados, pois este evento roda novamente na Thread em que o Form foi criado, permitindo modificar os controles sem ocorrer nenhum problema.
KURTGU 24/08/2015 18:54:06
#450440
Ocelot sim se eu tirar essa linha da o erro que voce falou....
DS2T 25/08/2015 00:57:54
#450455
Resposta escolhida
Pois é, o OCELOT está certo.
Essa propriedade é só um jeito de desprezar os erros de acesso a thread principal, isso pode acabar dando efeitos indesejados na sua aplicação e você nunca vai descobrir que é justamente essa maldita.

Existem muitas formas de lidar com acesso a thread no .Net.
Eis aqui uma sugestão pro seu caso:



Imports System.Threading

Public Class Form1

Private minhaThread As Thread
Private i As Integer = 0
Private Const numeroItens As Integer = 200

Private Sub PreencheListView()

For Me.i = 1 To numeroItens
AdicionaLista()
Thread.Sleep(100)
Next

End Sub

Private Sub AdicionaLista()
If Me.InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf AdicionaLista))
Else
ListView1.Items.Add(i)
ProgressBar1.Value = ListView1.Items.Count * 100 / numeroItens
ListView1.Update()
End If
End Sub


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
minhaThread = New Threading.Thread(AddressOf PreencheListView)

minhaThread.Start()

End Sub
End Class



Outra forma legal de fazer também é usando a classe Mutex, depois dá uma pesquisada.

Esse BackgroundWorker funciona bem em casos com banco de dados ou algum algoritmo que gere uma coleção ou algo do tipo. No DoWork você processa esses dados e deixa na memória. E no evento de finalização, você vai lá e faz o acesso ao controle de forma segura. Mas nesse seu caso, como é só um contador, não tem muita utilidade.

Beleza? Falou!
KURTGU 25/08/2015 09:43:11
#450463
DS2T Muito Obrigada vou da uma estudada no que o OCELOT me passou...
Tópico encerrado , respostas não são mais permitidas