Posteado por: toniogago | 15 marzo 2010

Realizar un proceso Batch con ASP.NET


En algunas aplicaciones web necesitamos realizar procesos que pueden durar bastante tiempo y la página nos devuelve un error de TimeOut. Estos procesos se suelen denominar batch o por lotes.
 

Pongamos un ejemplo

Protected Sub CmdIniciar_Click(ByVal Sender As Object, ByVal e as System.EventArgs) Handles CmdIniciar.Click
  ‘Espera 91 segundos. Por defecto ASP.NET el TimeOut son 90 S.
  Thread.Sleep(91000)
  ‘Para utilizar Thread debe estar importado System.Threading
End Sub
En este caso si el TimeOut está en 90 segundos, la página nos devolverá un error.
 

El proceso Batch

Para solucionarlo he utilizado un ThreadStart y un Thread de la siguiente forma:
Protected Sub CmdIniciar_Click(ByVal Sender As Object, ByVal e as System.EventArgs) Handles CmdIniciar.Click
   Dim ts as ThreadStart = New ThreadStart(AddressOf Calcula)
   Dim Trabajo as Thread = New Thread(ts)
   Trabajo.Start()
End Sub
Private Sub Espera()
   Thread.Sleep(91000)
End Sub
El problema que tengo ahora es que no sé si el proceso batch termina correctamente ya que se ejecuta como un proceso aparte y el usuario no se entera.
 

Clases compatidas

La solución a este segundo problema la solventé con una clase compartida. Se pueden crear clases reutilizables guardándolas en una carpeta denominada App_Code. Al crear un nuevo elemento en el proyecto de tipo clase, Visual Studio nos avisa de ello:
 
 Nueva clase en App_Code
 
Podeis encontrar más información en Microsoft. El código de la clase sería:
Public Class TrabajoBatch Private Shared _Procesando As Boolean = False
   Private Shared _Mensaje As String = “”
   Public Shared ReadOnly Property Procesando() As Boolean
      Get Return _Procesando
      End Get End
   Property Public Shared Property Mensaje() As String
      Get
         Mensaje = _Mensaje
      End Get
      Set(ByVal value As String)
         _Mensaje = value
      End Set
   End Property
   Public Shared Sub Procesar()
      _Procesando = True
      _Mensaje = “”
   End Sub
   Public Shared Sub Terminado()
      _Procesando = False
      _Mensaje = “”
   End Sub
End Class
Ahora podemos modificar la página con el siguiente código:
Protected Sub CmdIniciar_Click(ByVal Sender As Object, ByVal e as Private Sub Espera()
   TrabajoBatch.Procesar()
   Thread.Sleep(91000)
   TrabajoBatch.Terminado()
End Sub
Añadimos a la página un control timer y una etiqueta para comprobar cada cierto tiempo el estado del trabajo, y en el evento Tick ponemos lo siguiente: 
Protected Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
   lblTexto.Text = TrabajoBatch.Mensaje
End Sub
Como el control timer genera un Postback, tendremos que poner en el evento Page_Load lo siguiente:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   If Not IsPostBack Then
      Timer1.Interval = 1000 
      Timer1.Enabled = False
   End If
   If TrabajoBatch.Procesando Then
      CmdIniciar.Enabled = False
      Timer1.Enabled = True
   Else
      CmdIniciar.Enable = True
      Timer1.Enabled = False
   End If
End Sub
Tal como lo tenemos ahora, el usuario pulsará el botón Iniciar y el proceso en batch empezará deshabilitando el botón hasta que termine. Hay que tener cuidado en el proceso e intentar capturar los posibles fallos ya que si esto ocurre el usuario tendrá la impresión que el trabajo no termina.
Un saludo
Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Categorías

A %d blogueros les gusta esto: