A renderização da interface gráfica do Windows Phone 7 foi projetada para buscar o máximo de performance que o smartphone pode proporcionar, a UI Thread é responsável pelo desenho da interface principal do aplicativo, quando criamos um software para o WP7, devemos evitar bloquear a UI Thread, pois ela está diretamente relacionada a performance do software e também com a experiência do usuário com o aplicativo.

Os smartphones com Windows Phone 7, tem disponível um recurso que utiliza a aceleração da GPU, aumentando consideravelmente o desempenho gráfico para algumas tarefas relacionadas a manipulação de imagens e animações, principalmente as que usam a rotação de eixos, escalas e alguns tipos de  animações que usam de Storyboard. Não é necessário acionar nada para que alguns tipos de Storyboards utilizem esse recurso, eles automaticamente usam o Composition Thread ou também chamado de Render Thread.

O Render Thread pode ser usado para animações simples utilizando DoubleAnimation ou Easing Functions, ou em propriedades  como Opacity, Render Transforms e Rectangular Clip. Habilitando o EnableRedrawRegions podemos ver quais regiões na aplicação estão sendo desenhadas no momento, visualizando  quadro a quadro:

Application.Current.Host.Settings.EnableRedrawRegions = true;

Composition Frame Rate Thread  e UI Frame Rate Thread

 

Quando executamos um aplicativo através do Visual Studio 2010 com o smartphone plugado no computador,  podemos visualizar alguns números no lado superior direito da tela, esses números servem para você ter como parâmetro alguns pontos sobre a renderização gráfica, memória, etc, os dois primeiros números de 3 dígitos são referente a Render Thread e a UI Thread.

O Composition Frame Rate Thread está associado a velocidade com que a tela é atualizada em uma thread separada da UI Thread, como referência, o Windows Phone 7 utiliza o valor 30 como ponto de equilíbrio, ou seja, quando for abaixo de 30, os números estarão na cor vermelha, acima de 30 ele ficará com a cor default, o valor mais próximo de uma boa performance é 60, sua aplicação deve buscar sempre se aproximar desse número.

O UI Frame Rate Thread mostra a taxa de atualização da Thread principal, enquanto a interface do usuário estiver ativa, o valor de 30 também foi definido como ponto de equilíbrio, ficando vermelho se a aplicação estiver abaixo deste valor, porém este valor deve ser acima de 20 para ter um tempo de resposta aceitável e quanto maior o valor , o tempo de resposta será mais rápido.

Exemplo prático de UI Thread VS Render Thread

Vou criar um aplicativo simples com dois elementos Ellipse na tela, um com o nome BolaVermelha e outro com BolaAzul, as duas Ellipses serão animadas na tela, a BolaAzul vai utilizar o Render Thread, pois vamos utilizar uma Storyboard com a propriedade RenderTransform, já a BolaVermelha vamos anima-lá atualizando a mesma propriedade, mas utilizando um timer DispatcherTimer para atualizar a propriedade, ou seja, não utilizaremos uma Storyboard para realizar a animação e ela estará utilizando a UI Thread.

public partial class MainPage : PhoneApplicationPage
{
    DispatcherTimer timer;
    RotateTransform rotateVermelho;

    bool bateVolta;
    int contador = 0;

    public MainPage()
    {
        InitializeComponent();

        Loaded += new RoutedEventHandler(MainPage_Loaded);
        Application.Current.Host.Settings.EnableRedrawRegions = true;
        this.BolaVermelha.RenderTransform = new RotateTransform();
        this.BolaAzul.RenderTransform = new RotateTransform();

        rotateVermelho = BolaVermelha.RenderTransform as RotateTransform;
        rotateVermelho.Angle = -50;

        timer = new DispatcherTimer();
        timer.Tick += new EventHandler(timer_Tick);
        timer.Interval = new TimeSpan(0, 0, 0, 0, 33);
        timer.Start();

        bateVolta = false;
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        Storyboard storyboard = new Storyboard();
        DoubleAnimation animation = new DoubleAnimation();

        animation.From = 0;
        animation.To = 180;
        animation.Duration = new Duration(new TimeSpan(0, 0, 1));
        animation.AutoReverse = true;

        Storyboard.SetTarget(animation, this.BolaAzul.RenderTransform);
        Storyboard.SetTargetProperty(animation, new PropertyPath("Angle"));

        storyboard.Children.Add(animation);
        storyboard.RepeatBehavior = RepeatBehavior.Forever;
        storyboard.Begin();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        if (rotateVermelho.Angle == 120)
        {
            bateVolta = true;
        }

        if (rotateVermelho.Angle == -50)
        {
            bateVolta = false;
        }

        if (bateVolta == true)
        {
            rotateVermelho.Angle -= 1;
        }
        else
        {
            rotateVermelho.Angle += 1;
        }

        contador++;

        if (contador == 600)
        {
            MessageBox.Show("Parando a UI Thread");
            Thread.Sleep(1000);
        }

        if (contador == 1000)
        {
            MessageBox.Show("Inserindo BitmapCache");
            BitmapCache cache = new BitmapCache();
            BolaVermelha.CacheMode = cache;
        }
    }
}

Na linha 68 criei um contador, quando chegar a 600, ele vai bloquear a UI Thread, na linha 73, a UI Thread é bloqueada propositalmente utilizando Thread.Sleep, neste momento você irá notar que a animação da  BolaVermelha irá parar com base no tempo definido em Sleep, pois a sua Thread está bloqueada, mas a BolaAzul continuará a se movimentar.

Quando o contador chegar a 1000,  vou adicionar um BitmapCache na propriedade CacheMode da BolaVermelha, em alguns casos onde não estamos utilizando a Render Thread, podemos criar um cache, ou seja, colocar os bitmaps na memória, e com isso aproveitar da aceleração da GPU, com performance semelhante a Composition Thread, porém a BolaVermelha continuará na UI Thread,  uma simples mensagem na tela utilizando um MessageBox irá bloquear a UI Thread enquanto a BolaAzul continuará em movimento.

Conclusão

UI Thread e Composition Thread são recursos fundamentais que o Windows Phone 7 utiliza para apresentar a interface gráfica, conhecendo essas Threads você poderá melhorar a perfomance da sua aplicação, os smartphones são equipamentos limitados se comparado a um PC, conhecer quando utilizar determinado recurso pode fazer muita diferença, existem diversos outros pontos a serem considerados quanto ao monitoramento da aplicação com objetivo de melhorar a perfomance, neste artigo somente apresentei uma introdução sobre o assunto.

Alguns recursos podem não funcionar como esperado no emulador, pois depende de diversos fatores como o suporte a DirectX pela placa de video, neste link você encontra mais informações:

WP7/Silverlight Graphics Performance

Mais informações sobre Bitmap Cache : Bitmap Cache

Mais informações sobre performance: Performance Considerations in Applications for Windows Phone 

 

Categorias: artigos
Tags: