Quem procurar por um controle Timer na toolbox do WPF ou Silverlight, como de costume em aplicações Windows Forms ou VB6, não irá encontrar. O conceito de Timers é diferente, pois usa Multithreading, o que faz com que o uso seja muito cuidadoso. Se você tentar mudar uma propriedade de um objeto (elemento visual) da tela, vai receber um erro. Para evitar o trabalho tedioso de controlar as threads, você pode utilizar um tipo especial de Timer, chamado DispatcherTimer, que roda na Thread principal da aplicação, na interface do usuário. Assim você pode controlar objetos da tela de acordo com tempo configurado no Timer.

Como sempre, existem vantagens e desvantagens, porém a maior vantagem é o fato de rodar na thread principal. Um exemplo de cenário, seria a necessidade de periodicamente acessar um WebService para obter dados novos e atualizar uma grid ou gráfico na tela. Como desvantagem, pelo fato dele não usar Multithreading verdadeira, uma aplicação que precisa fazer pequenas tarefas em frações de segundo ou precisa ser mais responsiva com operações de alta latência, é aconselhável usar o System.Threading.Timer .

Vamos aqui fazer um pequeno exemplo de utilização:

Crie um projeto do tipo Silverlight Application no Visual Studio 2008.

clip_image002

 

Essa é a estrutura do projeto:

clip_image004

E este é nosso código XAML:

Aqui na MainPage.XAML foi criado um botão com uma ellipse que mudará de cor (vermelho ou verde), um TextBlock que mostra o estado da thread (Parado ou Processando) e um StackPanel onde será adicionado novos controles a cada segundo.

<UserControl x:Class="TimerSilverlight.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot; xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;

    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

  <Grid x:Name="LayoutRoot">

        <Button Height="32" x:Name="btnIniciar" Width="126" Click="btnIniciar_Click">

            <StackPanel Orientation="Horizontal">

                <Ellipse Fill="Red" Height="24" HorizontalAlignment="Left" Name="Ellipse1" Stroke="Black" Width="25" />

                <TextBlock Text="Parado" Height="28" HorizontalAlignment="Right" Name="lblStatus"/>

            </StackPanel>

        </Button>

        <StackPanel Width="300" x:Name="stackP" />

    </Grid>

</UserControl>

 

Vamos para o code behind da página (MainPage.xaml.vb)

O DispatcherTimer fica no Namespace System.Windows.Threading.DispatcherTimer e aqui fazemos a declaração do Timer(dt) e uma variável (_threadRun) para controlar o processo.

    Dim dt As New System.Windows.Threading.DispatcherTimer

    Private _threadRun As Boolean = False

 

No Load da página adicionamos um delegate para o método processar. Em seguida definimos o intervalo (1 seg.) e damos inicio ao timer:

 

    Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        AddHandler dt.Tick, AddressOf Processar

        dt.Interval = New TimeSpan(0, 0, 1)

        dt.Start()

    End Sub

 

Na sub Processar, verificamos se a thread está rodando e atualizamos a Interface do usuário, mudando a cor do circulo para vermelho(Parado) ou verde (Processando), adicionando um novo TextBlock a cada segundo.

    Private Sub Processar()

        If _threadRun Then

            Ellipse1.Fill = New SolidColorBrush(Colors.Green)

            lblStatus.Text = "Processando"

            Dim t As New TextBlock

            t.Text = "Processando"

            stackP.Children.Add(t)

        Else

            Ellipse1.Fill = New SolidColorBrush(Colors.Red)

            lblStatus.Text = "Parado"

            stackP.Children.Clear()

        End If

    End Sub

O botão apenas muda o estado da variável _threadRun:

    Private Sub btnIniciar_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

        If _threadRun Then

            _threadRun = False

        Else

            _threadRun = True

        End If

    End Sub

 

O código completo da página fica assim:

Partial Public Class MainPage

    Inherits UserControl

 

    Dim dt As New System.Windows.Threading.DispatcherTimer

    Private _threadRun As Boolean = False

 

    Public Sub New()

        InitializeComponent()

    End Sub

 

    Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        AddHandler dt.Tick, AddressOf Processar

        dt.Interval = New TimeSpan(0, 0, 1)

        dt.Start()

    End Sub

 

    Private Sub Processar()

        If _threadRun Then

            Ellipse1.Fill = New SolidColorBrush(Colors.Green)

            lblStatus.Text = "Processando"

            Dim t As New TextBlock

            t.Text = "Processando"

            stackP.Children.Add(t)

        Else

            Ellipse1.Fill = New SolidColorBrush(Colors.Red)

            lblStatus.Text = "Parado"

            stackP.Children.Clear()

        End If

    End Sub

 

    Private Sub btnIniciar_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

        If _threadRun Then

            _threadRun = False

        Else

            _threadRun = True

        End If

    End Sub

 

End Class

Rode a aplicação (F5) e no browser, clicando no botão, devemos ter as seguintes situações:

Antes de clicar

Depois de clicar

clip_image006

clip_image008

 

Dessa forma conseguimos demonstrar o uso do Timer numa aplicação Silverlight. Lembrando que o mesmo serve para aplicações WPF.

 

Abraços e bons estudos!

Anúncios