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.ThreadingEnd 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.ClickDim ts as ThreadStart = New ThreadStart(AddressOf Calcula)Dim Trabajo as Thread = New Thread(ts)Trabajo.Start()End SubPrivate 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:
Podeis encontrar más información en Microsoft. El código de la clase sería:
Public Class TrabajoBatch Private Shared _Procesando As Boolean = FalsePrivate Shared _Mensaje As String = “”Public Shared ReadOnly Property Procesando() As BooleanGet Return _ProcesandoEnd Get EndProperty Public Shared Property Mensaje() As StringGetMensaje = _MensajeEnd GetSet(ByVal value As String)_Mensaje = valueEnd SetEnd PropertyPublic Shared Sub Procesar()_Procesando = True_Mensaje = “”End SubPublic Shared Sub Terminado()_Procesando = False_Mensaje = “”End SubEnd 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.TicklblTexto.Text = TrabajoBatch.MensajeEnd 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.LoadIf Not IsPostBack ThenTimer1.Interval = 1000Timer1.Enabled = FalseEnd IfIf TrabajoBatch.Procesando ThenCmdIniciar.Enabled = FalseTimer1.Enabled = TrueElseCmdIniciar.Enable = TrueTimer1.Enabled = FalseEnd IfEnd 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
Advertisement
