AJUDA COM BACKGROUND WORKER
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
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
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.
===============================
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.
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.
Propriedade | Valor do Tipo | Descrição[td] |
Integer | O valor máximo do intervalo exibido no controle. O valor padrão é 100 - Read/Write. | |
Minimum | Integer | O valor mÃnimo do intervalo exibido pelo controle. O valor padrão é 0. Read/Write. |
Step | Integer | A quantidade pela qual a barra de progresso é incrementada quanto o método PerformStep é chamado. Valor padrão é zero. Read/Write. |
Value | Integer | A 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.
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...
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
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
NickSoft ele continua nao preenchendo a progressbar completamente....
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:
[][ô]s,
Tunusat.
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.
aki foi normal....
com o código aparecendo tmb
com o código aparecendo tmb
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:
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.
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.
Ocelot sim se eu tirar essa linha da o erro que voce falou....
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:
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!
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!
DS2T Muito Obrigada vou da uma estudada no que o OCELOT me passou...
Tópico encerrado , respostas não são mais permitidas