Página 1 de 1

Delay em C#

MensagemEnviado: 19 Ago 2014 15:31
por xultz
Eu estou tentando fazer um programa e preciso fazer uns delays de 1 segundo, e por incrível que pareça não estou conseguindo de jeito nenhum.

O que eu tenho é uma placa ligada na porta serial. Pela serial eu mando um comando, a placa executa, e dispara um processo analógico que eu preciso esperar pelo menos 1 segundo até estabilizar. Aí eu faço uma leitura para ver se o sinal analógico está dentro do limite desejado. Eu preciso fazer isso 7 vezes, em cada vez eu mando um comando diferente, e espero uma leitura de valor diferente.

Inicialmente, eu fiz assim:
Eu criei um botão que dispara a o processo, e uma progressBar. A cada leitura bem sucedida, eu incremento a progressBar.
Mais ou menos assim:

Código: Selecionar todos

progressBar.Value = 0;

// envio o comando pela serial
Thread.Sleep(1000);
// faço a leitura pela serial
// verifico se a resposta está ok, caso contrário gero erro via MessageBox, e retorno, se estiver OK continuo

progressBar.Value = 1;

// envio o comando pela serial
Thread.Sleep(1000);
// faço a leitura pela serial
// verifico se a resposta está ok, caso contrário gero erro via MessageBox, e retorno, se estiver OK continuo

progressBar.Value = 2;

// envio o comando pela serial
Thread.Sleep(1000);
// faço a leitura pela serial
// verifico se a resposta está ok, caso contrário gero erro via MessageBox, e retorno, se estiver OK continuo


e assim por diante, 7 vezes.

Problemas:
- O método Thread.Sleep congela a janela inteira, durante esse período ela fica sem resposta.
- Devido ao congelamento da janela, o progressBar cresce de forma totalmente dessincronizada com o que está sendo executado.

Eu tentei criar uma Thread, executar aquilo tudo na Thread, para que ela durma e não a janela. O problema é que a thread dorme antes de mandar a informação para a progressBar, e ela continua fora de sincronia.

Eu catei vários exemplos, e nenhum deles resolveu o problema.

Alguém aí tem uma dica do que eu posso fazer?

Estou usando Visual Studio 2010 (o 2013 ficou absurdamente lento no meu computador).

Obrigado!

Re: Delay em C#

MensagemEnviado: 19 Ago 2014 15:57
por andre_luis
Não conheço dessa linguagem de programação, mas não existe nenhum método para obter o horário do relógio ?
Alguns sistemas retornam valor com precisão na casa de milisegundos, o que presumo poderia atender nesse caso.

Re: Delay em C#

MensagemEnviado: 19 Ago 2014 16:33
por xultz
Tem, mas daí teria que ficar no loop while(tempo) e isso faz com que o Windows pire.

Re: Delay em C#

MensagemEnviado: 19 Ago 2014 16:51
por Maffeis
se usar um timer programado para 1 segundo

vc habilita e desabilita e utiliza o evento quando for necessário.

Re: Delay em C#

MensagemEnviado: 19 Ago 2014 19:01
por Red Neck Guy
A melhor forma de se fazer isso é utilizando threads.
Você deve criar uma thread que faz a manipulação do protocolo e utilizar o Invoke para acessar um delegate que acessa o progressbar ou janela que queria atualizar.
A thread da interface não pode acessada diretamente por outra.

Re: Delay em C#

MensagemEnviado: 19 Ago 2014 20:41
por xultz
Eu tentei, Aquino, mas mesmo assim ficou fora de sincronia, parece que o comando de setar a progressbar é dormido junto com a thread, depois que a thread acorda a progressbar é atualizada.
Eu testei com VS 2012 usando o parâmetro await e aparentemente está rolando.

Re: Delay em C#

MensagemEnviado: 21 Ago 2014 11:52
por chipselect
se está sobrando cpu (geralmente está), deveria não sair muito do "sincronismo".

Como é sua thread, é mais ou menos parecido com o código abaixo?

Código: Selecionar todos
       new Thread(new ThreadStart(new Action(()=>{
                int contadorAte7 = 0;
                while (contadorAte7 < 7)
                {
                    Thread.Sleep(1000);
                    contadorAte7++;
                    if (progressBar1.InvokeRequired)
                    {
                        progressBar1.Invoke(new Action(() =>
                        {
                            progressBar1.Value++;
                        }));
                    }
                    else
                    {
                        progressBar1.Value++;
                    }
                }
                if (this.InvokeRequired)
                {
                    this.Invoke(new Action(() =>
                    {
                        MessageBox.Show("Fim");
                    }));
                }
                else
                {
                    MessageBox.Show("Fim");
                }
            }))).Start();


PS: o bloco do "else" para os "InvokeRequired" não são necessários, pois não serão executados, mas o código foi colocado devido ao costume de programação (vício).