ASP .NET - Realizando o agendamento de tarefas


 Neste artigo eu vou mostrar como podemos realizar o agendamento de tarefas em aplicações web usando os recursos da ASP .NET Web Forms.

Não é raro termos que executar um código em uma determinada data e hora ou repetir a execução de uma rotina em um intervalo de tempo regular. No caso de aplicações ASP .NET essas tarefas podem estar relacionadas com o envio de emails, análise de tráfego, criação de relatórios, manutenção de tarefas, etc.

A ASP .NET não fornece uma forma simples e direta de realizar o agendamento de tarefas. Além disso, tudo o que o protocolo HTTP, na qual a ASP .NET esta baseada, pode fazer é retornar uma resposta após receber uma requisição.

Felizmente, existem várias soluções para resolver este problema. Assim podemos dividir o agendamento de tarefas em dois grupos:

  1. - Usar métodos ASP.NET, como o uso do timer, expiração do cache ou threads;
  2. - Usar aplicativos externos, como o Agendador de Tarefas do Windows, um serviço do Windows, um programa de automação de hospedagem, etc.;

Neste artigo eu vou focar apenas na utilização dos recursos da ASP .NET e mostrar 3 maneiras de simular o agendamento de tarefas.

Nota: Usar apenas métodos ASP.NET é uma opção se você tiver uma hospedagem compartilhada, mas eles têm alguns inconvenientes.

Recursos usados:

Criando o projeto no Visual Studio 2013 Express for web

Abra o VS Express 2013 for web e clique em New Project;

A seguir selecione a linguagem Visual Basic e o template ASP .NET Web Application;

Informe o nome Agendando_Tarefas e clique no botão OK;

A seguir selecione o template Empty, marque o folder Web Forms e clique no botão OK;

Será criado um projeto Web Form com a seguinte estrutura exibida na janela Solution Explorer:

1- Agendando tarefas usando Threads

Utilizar threads é uma solução simples. Para isso nos usamos o procedimento Application_Start no arquivo Global.asax para iniciar a tarefa. Então, em uma thread separada nós chamamos a tarefa novamente em intervalos de tempo regulares.

Agora podemos abrir o arquivo Global.asax e definir o código abaixo que é um modelo que podemos usar para realizar o agendamento de uma tarefa:

Imports System.Threading
Public Class Global_asax
    Inherits HttpApplication
    Sub Application_Start(sender As Object, e As EventArgs)
        ' Na inicialização da aplicação cria um inicio em uma thread separada
        Dim tsTarefa As ThreadStart = New ThreadStart(AddressOf TarefaLoop)
        Dim MinhaTarefa As Thread = New Thread(tsTarefa)
        MinhaTarefa.Start()
    End Sub
    Shared Sub TarefaLoop()
        ' Neste exemplo a tarefa será repetida em um loop infinito
        ' Você pode adicionar um parâmetro se desejar ter uma opção para para a tarefa
        While (True)
            ' Executa a tarefa agendada
            TarefaAgendada()
            ' Aguarda por um certo intervalo de tempo
            System.Threading.Thread.Sleep(TimeSpan.FromHours(12))
        End While
    End Sub
    Shared Sub TarefaAgendada()
        ' Código da tarefa que irá ser executada periodicamente
    End Sub
End Class

2- Agendando tarefas usando Timers

Podemos usar Timers para agendar tarefas e novamente vamos usar o método Application_Start do arquivo Global.asax. No método Application_Start podemos criar um Timer e usar o evento Elapsed para executar uma tarefa em intervalo regulares de tempo.

O evento Elapsed do controle Timer ocorre quando o intervalo decorrer.

Se a propriedade Enabled for definida como true e AutoReset como false, o Timer gera o evento Elapsed somente uma vez, a primeira vez que o intervalo decorre. Se Interval for definido após o Timer ter iniciado, a contagem é redefinida.

Vejamos um modelo como exemplo

Imports System.Threading
Public Class Global_asax
    Inherits HttpApplication
    Protected Sub Application_Start(ByVal sender As Object, ByVal e As System.EventArgs)
        ' Cria um timer dinamicamente
        Dim timerTarefaAgendada As System.Timers.Timer = New System.Timers.Timer()
        ' Define a propriedade Interval do Timer em milisegundos,
        ' Neste exemplo vamos executar a tarefa a cada minuto
        timerTarefaAgendada.Interval = 60 * 1000
        timerTarefaAgendada.Enabled = True
        ' Inclui um manipulador para o evento Elapsed
        AddHandler timerTarefaAgendada.Elapsed, AddressOf timerTarefaAgendada_Elapsed
    End Sub
    Sub timerTarefaAgendada_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
        'Executa a tarefa
        TarefaAgendada()
    End Sub
    Sub TarefaAgendada()
        ' Define o código que será executado periodicamente
    End Sub
End Class

Atenção !! ao usar este recurso você deve saber que o controle Timer é instável em aplicações web. É comum que o Timer pare depois de um certo tempo após a execução, especialmente em uma hospedagem compartilhadas onde o hosting tenta economizar recursos e recicla a aplicação web.

3- Agendando tarefas usando  a expiração do cache

Utilizar a expiração do Cache da ASP .NET é mais um método que você pode usar para criar tarefas agendadas. Neste método, não é importante o que você coloca no cache. Neste exemplo vamos adicionar uma string "1", mas poderia ser qualquer coisa. A utilização para tarefas agendadas vem do fato de que o cache expira após intervalo de tempo especificado e, em seguida, executa a função selecionada (tarefa agendada).

ASP.NET implementa a classe System.Web.Caching.Cache para armazenar objetos que requerem um grande quantidade de recursos do servidor para serem criados ,  forma que eles não tenham  que ser recriados a cada vez que for necessário.

Instâncias da classe cache são criadas para cada domínio da aplicação e permanecem ativos enquanto o domínio da aplicação permanecer ativo. Quando uma aplicação é reiniciada a classe cache é recriada.

Você pode acessar via código a informação sobre uma instância da classe cache através da propriedade cache , do objeto HttpContext ou do objeto Page.

A classe cache permite que você adote uma política de expiração para itens no cache. Itens podem ser definidos para expirar em um tempo específico; este tempo é chamado de absolute expiration. Podem também expirar se não forem acessados por período de tempo conhecido como sliding expiration. Itens que expiraram retornam um valor null.

Ao utilizar o cache para colocar os seus dados você pode aumentar o desempenho da sua aplicação pois usando o cache você evita que a aplicação tenha que ir/voltar diversas vezes ao servidor.

Usando novamente o arquivo Global.asax temos a seguir um exemplo que usa a expiração do cache:

Imports System.Threading
Public Class Global_asax
    Inherits HttpApplication
    Protected Sub Application_Start(ByVal sender As Object, ByVal e As System.EventArgs)
        ' Agenda a tarefa pela primeira vez
        TarefaAgendada()
    End Sub
    Shared Sub TarefaAgendada()
        ' O Cache vai experir depois de uma hora
        ' Você pode alterar este intervalo conforme sua necessidade
        ' A função SetTImer será chamada quando o cache expirar
        HttpRuntime.Cache.Add("TarefaAgendada", "1", Nothing, Cache.NoAbsoluteExpiration,
                              TimeSpan.FromHours(1), CacheItemPriority.NotRemovable,
                              New CacheItemRemovedCallback(AddressOf SetTimer))
    End Sub
    ' Esta função será chamada quando o cache expirar
    Shared Sub SetTimer(ByVal key As String, ByVal value As Object, ByVal reason As CacheItemRemovedReason)
        ' Chama a função da tarefa
        DoTarefa()
        ' Agenda uma nova execução
        TarefaAgendada()
    End Sub
    Shared Sub DoTarefa()
        ' Aqui vai o código da tarefa que seráe executada periodidamente
        ' Neste exemplo será executado após uma hora
    End Sub
End Class

Neste artigo eu mostrei 3 maneiras simples de agendar tarefas usando os recursos da ASP .NET mas não se iluda essa simplicidade tem um custo.

Existem muitos problemas que você deve considerar ao usar estes recursos como direitos insuficientes para serem executados, pois por padrão a ASP .NET é executada como um serviço de rede e possui uma conta com poderes limitados dependendo do ambiente.

Além disso, a aplicação ASP.NET pode reiniciar ou até mesmo parar de trabalhar por causa de vários motivos. Se a aplicação ASP.NET para, as tarefas agendadas não serão executados. (Se não há requisições sendo feitas o servidor pode parar a aplicação após um curto período de tempo.)

Então é importante você ter isso em mente ao decidir usar esses recursos. Em outro artigo irei mostrar como podemos agendar tarefas de forma mais robusta.

João 5:24 Na verdade, na verdade vos digo que quem ouve a minha palavra, e crê naquele que me enviou, tem a vida eterna, e não entrará em condenação, mas passou da morte para a vida.

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti