BACKGROUNDWORKER + PROGRESSBAR

ROGERIOAZEVEDO 16/04/2014 23:18:49
#437386
Boa noite.

Nobres colegas, tenho uma aplicação Windows Forms com C#. Essa aplicação possui um form principal, e vários outros forms são abertos dentro desse (MDI Container) esses [Ô]subforms[Ô] são charts e datagrids. Alguns deles demoram para carregar e dão a sensação ao usuario que a aplicação travou. Quero colocar uma ProgressBar no form principal para mostrar ao usuário que o form solicitado por ele está sendo carregado.

  private void Carregar()
{
try
{
using (SqlCommand Cmd01 = new SqlCommand())
{
Cmd01.CommandText = Classes.Querrys.OS_Mes;

//Cria Parametros para substituir na Querry
Cmd01.Parameters.Add([Ô]@data1[Ô], SqlDbType.DateTime);
Cmd01.Parameters[[Ô]@data1[Ô]].Value = String.Format([Ô]{0:yyyy/MM/dd} {1}[Ô], this.dtpIni1.Value, [Ô]00:00:00[Ô]);
Cmd01.Parameters.Add([Ô]@data2[Ô], SqlDbType.DateTime);
Cmd01.Parameters[[Ô]@data2[Ô]].Value = String.Format([Ô]{0:yyyy/MM/dd} {1}[Ô], this.dtpFim1.Value, [Ô]23:59:59[Ô]);

//Exibe os dados no Chart
DataView Grafico = new DataView(Classes.Conexao.GetBuscaSigma(Cmd01));
chtOrdem.Series[0].Points.DataBindXY(Grafico, [Ô]Mes[Ô], Grafico, [Ô]Abertas[Ô]);
chtOrdem.Series[1].Points.DataBindXY(Grafico, [Ô]Mes[Ô], Grafico, [Ô]Fechadas[Ô]);

chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisX.MajorGrid.Enabled = false;
chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisY.MajorGrid.Enabled = false;
chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisY.LabelStyle.Enabled = false;
chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisX.Interval = 1;
}
}

catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}


Pelo que pesquisei isso é feito com BackgroundWorker, pesquisei algo na internet, até fiz uma aplicação que há um botão e uma ProgressBar que enche ao apertar o botão, mas ainda não entendi como fazer o codigo fazendo o set Min e Max da progressbar e vincular o tempo do trabalho a ser realizado com o preenchimento da progress bar, como no exemplo a função acima Carregar(), a função preenche um chart, quero que o tempo de preenchimento do chart fosse acompanhado pela progress, e depois de devidamente carregado o form seja aberto, ou mostrado. é possivel?


  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;

for (int i = 0; i < 101; i++)
{
worker.ReportProgress(i);
System.Threading.Thread.Sleep(1000);
}
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{

}

private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
worker.RunWorkerAsync();
}

OCELOT 17/04/2014 07:32:41
#437391
Você não vai conseguir fazer isso assim.

Primeiro não existe como pegar o progresso de uma função, é a própria função (seu código) que tem que saber informar o progresso, e em alguns casos, como por exemplo dependendo de como se faz o acesso ao banco de dados pode não ter como calcular este progresso.

Outra coisa é que não só o código do progresso teria que ficar no backgroundworker, mas todo o código que demora para rodar deveria ficar nele, só que o problema ai é que nenhum código rodando fora do thread que criou o form deve modificar seus controles pois isso pode causar um comportamento totalmente inesperado nos controles, por exemplo eu já vi um caso em que um DataGrid era preenchido em um thread e com isso sumiam os column headers e algumas colunas não mostravam os dados.

Acho que o mais fácil seria exibir uma mensagem de aguarde enquanto você processa os dados.
ROGERIOAZEVEDO 17/04/2014 08:18:40
#437392
Obrigado pela Resposta Ocelot!

O que me disseram é que eu não colocaria no backgroundworker o processo completo, como por exemplo a consulta no banco, que não parece ser o que está demorando. Quado rodo a querry no ManagementStudio é bem rapida a consulta, o que parece demorar é o preenchimento da tela (Chart ou Datagrid). O que tinham me instruido é fazer o Set Min o gatilho da função e o set Max a [Ô]população[Ô] da ultima linha. Existe a possibilidade de fazer assim?

Outra coisa, alguns forms que demoram muito aparece a mensagem de [Ô]Não Respondendo[Ô] mas se o usuario esperar ele carrega, sei que há como aumentar o tempo para que esse erro não ocorra, mas não sei a sintaxe, poderia me ajudar, como no exemplo que dei acima?
ROGERIOAZEVEDO 17/04/2014 21:49:29
#437412
O que eu gostaria é de criar algo para que o usuário saiba que a tela está sendo carregada e que a aplicação não travou. No meu entendimento, fazer isso pelo preenchimento da tela seria algo simples, não estou considerando a consulta no banco, mas sim o preenchimento do chart ou do grid. Tem algo que eu possa fazer nesse sentido?
ROGERIOAZEVEDO 01/05/2014 22:44:55
#437840
Não sei se é exatamente o que eu preciso, mas para ajudar a explicar a minha necessidade, o link abaixo [Ô]aparenta[Ô] ser quase o que eu preciso...

http://code-programmming.blogspot.com.br/2013/12/backgroundworker-and-progress-bar-c.html

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Quando o usuário abrir o form, a barra começa a ser carregada mostrando ao usuário que a sua solicitação está sendo executada.
PERCIFILHO 15/05/2014 16:30:27
#438256
Porque você não usa uma GIF animada dentro de uma Picture, ao invés de uma barra de progresso?
Você pode procurar na NET, sempre se encontra.
Você deixa ela visível quando iniciar o carregamento, aí, a GIF fica rodando, piscando, por exemplo, enquanto você carrega tudo o que tem que carregar. Quando terminar, você torna ela invisível. Assim, você não precisa calcular o tempo que vai demorar para carregar tudo.
Até mais.
ROGERIOAZEVEDO 21/05/2014 17:15:16
#438388
A ideia é legal, tem algum link para me indicar para estudar a sintaxe de construção do conceito.
GUIMORAES 21/05/2014 17:36:33
#438389
Rogério
A utilização deste tipo de conceito é um pouco complicada, mais não é impossível.
Basicamente um progressbar precisa saber quando irá iniciar e quando irá finalizar o processo, quando isto está vinculado à uma consulta, fica meio difícil de se aplicar.
Você pode utilizar o que o PERCIFILHO disse, utilizar um gif animado, isto já da uma mudada no visual da tela. Para fugir um pouco de se utilizar uma Thread, você pode utilizar o Application.DoEvents para exibir o progresso.

Estou anexando um exemplo para você.
ROGERIOAZEVEDO 22/05/2014 18:12:16
#438424
Boa noite.

Eu encontrei alguns modelos usando BACKGROUNDWORKER, mas não consegui adequar os modelos na minha aplicação, as maiores dúvidas era vincular o preenchimento da tela com a PROGRESSBAR.

Pensei em fazer como o colega sugeriu, inserir uma GIF animada para mostrar o progresso, deve ser almo mais facil de fazer, mas ainda tenho dúvidas para vincular o gatinho entre o momento de iniciar a GIF e tirar a mesma após a tela ser preenchida.

Os colegas teriam algum modelo ou link para me indicar? Abaixo dou um exemplo da função que traz as informações.

  

private void Carregar()
{
try
{
using (SqlCommand Cmd01 = new SqlCommand())
{
Cmd01.CommandText = Classes.Querrys.OS_Mes;

//Cria Parametros para substituir na Querry
Cmd01.Parameters.Add([Ô]@data1[Ô], SqlDbType.DateTime);
Cmd01.Parameters[[Ô]@data1[Ô]].Value = String.Format([Ô]{0:yyyy/MM/dd} {1}[Ô], this.dtpIni1.Value, [Ô]00:00:00[Ô]);
Cmd01.Parameters.Add([Ô]@data2[Ô], SqlDbType.DateTime);
Cmd01.Parameters[[Ô]@data2[Ô]].Value = String.Format([Ô]{0:yyyy/MM/dd} {1}[Ô], this.dtpFim1.Value, [Ô]23:59:59[Ô]);

//Exibe os dados no Chart
DataView Grafico = new DataView(Classes.Conexao.GetBuscaSigma(Cmd01));
chtOrdem.Series[0].Points.DataBindXY(Grafico, [Ô]Mes[Ô], Grafico, [Ô]Abertas[Ô]);
chtOrdem.Series[1].Points.DataBindXY(Grafico, [Ô]Mes[Ô], Grafico, [Ô]Fechadas[Ô]);

chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisX.MajorGrid.Enabled = false;
chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisY.MajorGrid.Enabled = false;
chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisY.LabelStyle.Enabled = false;
chtOrdem.ChartAreas[[Ô]ChartArea1[Ô]].AxisX.Interval = 1;
}
}

catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Faça seu login para responder