VB .NET - 'Dando um tempo' no seu programa


Eu usei a expressão 'dar um tempo' no título do artigo pois vou mostrar como podemos retardar ou pausar a execução de um determinado trecho de código. Sim eu disse retardar, muito embora na maioria das vezes queremos que o código seja executado com a maior rapidez possível às vezes é preciso 'dar um tempo'.

Na linguagem VB .NET podemos retardar ou suspender a execução de um programa da seguinte forma:

Para usar o método Sleep você tem que declarar o namespace :  System.Threading;

Este método recebe um parâmetro que indica o número de milisegundos que você deseja pausar o programa. 

- Sleep(0) -  causa uma pausa de zero milisegundos;
- Sleep(5000) - causa uma pausa de 5 segundos;
- Sleep(1000) causa uma pausa de 1 segundo;

Para medir o tempo da pausa podemos usar a classe StopWatch conforme o código abaixo:

Temos uma aplicação Console que usa o método Sleep() para dar um tempo de 1 segundo e registro os horários de início e fim da tarefa:

Module Module1
 

Sub Main()


   ' Cria um Stopwatch e um sleep para 1 segundo

  Dim stopwatch As Stopwatch = stopwatch.StartNew 

   Console.WriteLine("Inicio da tarefa")

   Console.WriteLine(DateTime.Now.ToLongTimeString)


   System.Threading.
Thread.Sleep(1000)

   stopwatch.Stop()


   ' Escreve o tempo da pausa

   Console.WriteLine(stopwatch.ElapsedMilliseconds)

    Console.WriteLine(DateTime.Now.ToLongTimeString)

    Console.WriteLine("fim da tarefa")

    Console.ReadKey()

End Sub
 

End Module
 

A classe Stopwatch fornece um conjunto de métodos e propriedades que você pode usar para medir de uma maneira mais precisa o tempo transcorrido.

O classe Stopwatch  é muito útil para calcular o tempo que foi gasto entre dois intervalos de tempo em uma aplicação VB .NET.

Para usar o objeto Stopwatch   você precisa chamar o seu método Start para iniciar a contagem do tempo; o método Stop interrompe a contagem. O método Reset é útil para limpar a contagem do tempo iniciando o contador.

Temos a seguir a sequência das etapas usadas para usar esta classe:

'Primeiro você cria uma nova instância da classe
Dim cronometro As New Stopwatch

' Em seguida você inicia a contagem do tempo
cronometro.Start()

' Aguarda a realização da operação VB .NET

' Após o encerramento da tarefa você para a contagem do tempo
cronometro.Stop()

' Por último você exibe o tempo gasto para executar a tarefa em milisegundos
Debug.WriteLine(stopWatch.ElapsedMilliseconds.ToString)

Uma instância da classe StopWatch pode estar em execução (Running) ou parada (Stopped), para determinar o estado atual de uma instância StopWatch você usa o método IsRunning.

Pausando a execução do seu código

Para mostrar como dar um tempo na execução de um trecho de código vou usar uma aplicação VB .NET que desenha figuras gráficas de forma que o efeito da pausa pode ser melhor observado.

Abaixo temos o formulário principal e em cada um dos botões vemos qual deverá ser a tarefa a ser realizada pelo código da aplicação;

Em todos os exemplos irei 'dar um tempo' no código usando os recursos disponíveis:

 O evento Click do primeiro botão de comando - Desenhar Linhas -  temos o código a seguir:

 Private Sub BtnLinhas_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnLinhas.Click
        Dim iloop As Integer
        Dim ChgYPoint As Integer
        Dim ChgXPoint As Integer
        GraphicsObj = Me.Panel3.CreateGraphics()
        Me.Panel3.Refresh()

        ChgYPoint = 5
        ChgXPoint = 5

        For iloop = 1 To 106
            GraphicsObj.DrawLine(Pens.Blue, ChgXPoint, 0, 525, ChgYPoint)
            GraphicsObj.DrawLine(Pens.Blue, 0, ChgYPoint, ChgXPoint, 525)
            GraphicsObj.DrawLine(Pens.Blue, 0, (525 - ChgYPoint), ChgXPoint, 0)
            GraphicsObj.DrawLine(Pens.Blue, 525, ChgYPoint, (525 - ChgXPoint), 525)
            ChgYPoint = ChgYPoint + 5
            ChgXPoint = ChgXPoint + 5
            System.Threading.Thread.Sleep(200) ' retarda em 2 segundos
            Application.DoEvents()
        Next

    End Sub

 

O código que causa a pausa esta destacado em negrito:

            System.Threading.Thread.Sleep(200) ' retarda em 2 segundos
            Application.DoEvents()

O código causa uma pausa de 2 segundos usando o método Sleep() de System.Threading.Thread visto que esta o interior do laço for/next retardando assim sua execução.

Em seguida temos uma instrução que foi usada e que já é conhecida do VB6: DoEvents().

A instrução Application.DoEvents() permite que mensagens seja exibida durante a execução da pausa.

Quando você roda um programa Windows Forms, ele cria um novo formulário o que então aguarda pelos eventos a manipular.

A cada momento o formulário manipula um evento e processa todo o código associado a ele.

Todos os demais eventos ficam aguardando na fila. Enquanto o seu código trata um evento, sua aplicação não responde.

Ao chamar DoEvents no seu código, sua aplicação pode tratar outro eventos e diferentemente do VB6 o método DoEvents não chama o método Sleep.

Mas atenção a chamada deste método faz com que a thread atual seja suspensa enquanto todas as mensagens que estavam aguardando sejam processadas.

Existem outras maneiras de dar um pausa na execução de um trecho de código. Vejamos algumas delas:

1- Usando um laço for/next

Outra forma de dar uma pausa é usar um laço for/next que não realiza tarefa alguma, apenas gasta tempo para ser executado.

No botão - Desenhar Círculos - temos o código a seguir que usa este recurso:

 Private Sub BtnCirculos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnCirculos.Click
        Dim iloop As Integer
        Dim ChgRadius As Integer

        GraphicsObj = Me.Panel3.CreateGraphics()
        Me.Panel3.Refresh()
        ChgRadius = 10
        For iloop = 1 To 100
            GraphicsObj.DrawEllipse(Pens.Blue, 520 - ChgRadius, 520 - ChgRadius, ChgRadius, ChgRadius)
            GraphicsObj.DrawEllipse(Pens.Blue, 450 - ChgRadius, 450 - ChgRadius, 50, 50)
            ChgRadius = ChgRadius + 5
            'pausa usando um loop for/next
            For temploop = 1 To 3000000
            Next
        Next
    End Sub

 

 O código em negrito mostra o laço for/next que apenas gasta tempo dando assim uma pausa na execução do código.

É uma maneira não muito elegante e imprecisa pois o tempo de execução do laço vai depender da velocidade de processamento da máquina, e assim, o tempo pode variar muito entre máquinas diferentes.

2- Usando a função Sleep da API do Windows

A API do Windows reside em arquivos DLLs como User32.dll, Shell32.dll, etc localizados no diretório do sistema. Na DLL Kernel32.dll temos funções para tratar operações com arquivos e gerenciamento de memória.

Para usar esta função basta declarar no início do programa a seguinte linha de código:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Ela é bem parecida com o método Thread.Sleep do VB .NET e pausa a execução do programa por uma quantidade de milisegundos.

No evento Click do botão Desenhar Arcos temos a sua utilização no interior do laço for/next conforme o código a seguir:

 Private Sub BtnArcos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnArcos.Click
        Dim iloop As Integer
        Dim ChgXPoint As Integer
        Dim ChgYPoint As Integer
        Dim ChgWidth As Integer
        Dim ChgHeight As Integer
        ChgXPoint = 0
        ChgYPoint = 215
        ChgWidth = 200
        ChgHeight = 100

        GraphicsObj = Me.Panel3.CreateGraphics()
        Me.Panel3.Refresh()
        For iloop = 1 To 15
            GraphicsObj.DrawArc(Pens.Blue, ChgXPoint, ChgYPoint, ChgWidth, ChgHeight, 270, 180)
            ChgXPoint = ChgXPoint + 10
            ChgYPoint = ChgYPoint - 5
            ChgWidth = ChgWidth + 10
            ChgHeight = ChgHeight + 5
            'usando a função Sleep da API Do Windows
            Sleep(300)
            Application.DoEvents()
        Next

    End Sub

O exemplo acima vai dar uma pausa de mais ou menos 3 segundos na execução do código.

3- Usando a sua própria função

É claro que você mesmo pode definir uma função para dar uma pausa na execução do código. A seguir temos um exemplo onde em um Modulo eu defini a seguinte rotina:

Sub EsperaUmPouco(ByVal dblSecs As Double)

 

Const UmSeg As Double = 1.0# / (1440.0# * 60.0#)


   Dim
dblEsperarAte As Date

    Now.AddSeconds(UmSeg)

   dblEsperarAte = Now.AddSeconds(UmSeg).AddSeconds(dblSecs)

   Do Until Now > dblEsperarAte

         Application.DoEvents() 'permite que mensagens sejam processadas

   Loop


End Sub

Feito isto basta chamar a função passando como parâmetro um valor que indica o tempo da pausa que você deseja dar.

No evento Click do botão - Desenhar Strings - temos um exemplo de sua utilização:

 Private Sub BtnDrawString_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnDrawString.Click
        Dim iloop As Integer
        Dim FntSz As Integer = 10
        Dim Fnt As New Font("Verdana", FntSz)
        Dim ChgXPoint As Integer
        Dim ChgYPoint As Integer
        ChgXPoint = 20
        ChgYPoint = 20

        Me.Panel3.Refresh()
        For iloop = 1 To 9
            Fnt = New Font("Verdana", FntSz)
            GraphicsObj = Me.Panel3.CreateGraphics()
            GraphicsObj.DrawString("Macoratti", Fnt, Brushes.Blue, ChgXPoint, ChgYPoint)
            ChgXPoint = ChgXPoint + 10
            ChgYPoint = ChgYPoint + (iloop * 10)
            FntSz = FntSz + 5
            'Usando uma função própria para dar uma pausa
            EsperaUmPouco(2)
            Application.DoEvents()
        Next
    End Sub

 

Geralmente usamos retardar a execução de um programa para aguardar o término de uma tarefa como a cópia e/ou download de um arquivo e não devemos abusar deste recurso usando para forçar que determinadas tarefas sejam executadas.

Assim, dar um tempo na execução do seu programa, é uma tarefa relativamente simples.

Pegue o projeto completo aqui: DesenhoBasicoSleep.zip

Eu sei é apenas VB .NET, mas eu gosto...

Referências:


José Carlos Macoratti