Chalalo Land

Tecnologías ASP.NET y un poco Más

Contacto


 Si quierer cooperar, yo feliz, muy agradecido :)

De donde me Visitan?

Locations of visitors to this page

Generic Content

Si te gustaron los articulos, y te animas te estaría muy agradecido!


Recent Posts

Tags

Community

Blogs de MVP

Amigos Geeks

Blogs Imperdibles

GODS

Archives

Email Notifications

[Tips]Ejecutar métodos en paralelo en ASP.NET 3.5

Hola, en esta ocasión quiero volver a tocar el tema de la ejecución en paralelo de métodos en ASP.NET, que si bien está muy optimizado en la versión 4.5, que aún está en desarrollo, muchos de nosotros no tenemos planes a corto plazo de migrar para aprovechar las ventajas.

Veamos un escenario común, grillas grillas combos combos, a que me refiero con esto, es que muchas veces nuestros sistemas cargan una cantidad considerable de combos que no están asociados e igual cantidad de grillas en el Page Load. Generalmente no es necesario que esto se cargue secuencialmente, y podemos aprovechar las ventajas en términos de tiempo al utilizar la carga en paralelo.

Para explicar un poco más vamos a crear un pequeño proyecto, que tenga 2 DropDownList (o combos, como le llamamos universalmente). Cada uno de estos combos va a tener una duración de carga de 3 segundos, obviamente de manera secuencial se va a demorar mínimo 6 segundos la carga de la página, mientras que en paralelo, claro como el agua, mínimo 3 segundos:

image image

Carga Secuencial Triste

Carga Paralela Sonrisa

Ahora veamos el código

El código de la página con carga secuencial:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If Not Page.IsPostBack Then

            dd_ciudades.DataSource = Obtciudades()

            dd_ciudades.DataBind()

            dd_regiones.DataSource = Obtregiones()

            dd_regiones.DataBind()

        End If

End Sub

 

 

Public Function Obtciudades() As List(Of Ciudad)

   System.Threading.Thread.Sleep(3000)

   Dim ciudades As New List(Of Ciudad)

   ciudades.Add(New Ciudad With {.id = 1, .nombre = "Concepcion"})

   ciudades.Add(New Ciudad With {.id = 2, .nombre = "Santiago"})

   ciudades.Add(New Ciudad With {.id = 3, .nombre = "Viña del Mar"})

   ciudades.Add(New Ciudad With {.id = 4, .nombre = "Puerto Montt"})

   ciudades.Add(New Ciudad With {.id = 5, .nombre = "Cañete"})

   Return ciudades

End Function

 

 

Public Function Obtregiones() As List(Of Region)

   System.Threading.Thread.Sleep(3000)

   Dim regiones As New List(Of Region)

   regiones.Add(New Region With {.id = 1, .nombre = "Primera Region"})

   regiones.Add(New Region With {.id = 2, .nombre = "Segunda Region"})

   regiones.Add(New Region With {.id = 3, .nombre = "Tercera Region"})

   regiones.Add(New Region With {.id = 4, .nombre = "Cuarta Region"})

   regiones.Add(New Region With {.id = 5, .nombre = "Quinta Region"})

   Return regiones

End Function

Puedes notar los métodos Sleep para causar la demora en el thread de ejecución en cada uno de los métodos que sirvan para poblar los dropdownlist.Ahora si vemos la carga del la página con el IE Developer Toolbar, el resultado son 6.07 segundos:

image

Veamos el código para ASP.NET 3.5, es más largo pero la relación costo beneficio es muy buena, ya que vamos a bajar los tiempos casi a la mitad. Como dije anteriormente, implementar esta misma funcionalidad en ASP.NET 4.5 es mucho más sencillo, ya que elimina las complejidades al momento de especificar cuales métodos serán ejecutados de manera Asíncrona, pero eso lo dejaremos para otro post Sonrisa

Imports Microsoft.VisualBasic
Imports System.Threading 

 

Partial Class Paralelo

    Inherits System.Web.UI.Page

 

    Private ehRecuperarDatosDeDropDownList1 As EventHandler = Nothing

    Private ehRecuperarDatosDeDropDownList2 As EventHandler = Nothing

    Private listaRegiones As New List(Of Region)

    Private listaCiudades As New List(Of Ciudad)

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

  Dim pat1 As New PageAsyncTask(New BeginEventHandler(AddressOf
 
   Me.RecuperarDatosDeDropDownList1), New EndEventHandler(AddressOf
      Me
.CargarDropDownList1), Nothing, Nothing, True)

  Dim pat2 As New PageAsyncTask(New BeginEventHandler(AddressOf
      Me
.RecuperarDatosDeDropDownList2), New EndEventHandler(AddressOf
        Me
.CargarDropDownList2), Nothing, Nothing, True)

  Page.RegisterAsyncTask(pat1)

  Page.RegisterAsyncTask(pat2)

End Sub

 

#Region "dd_regiones"

Private Function RecuperarDatosDeDropDownList1(sender As Object, e As
      EventArgs
, cb As AsyncCallback, state As Object) As
IAsyncResult

      Me.ehRecuperarDatosDeDropDownList1 = New EventHandler(AddressOf
         Me.RecuperarRegiones)

     Return Me.ehRecuperarDatosDeDropDownList1.BeginInvoke(Me, 
     EventArgs
.Empty, cb, Nothing)
End Function

 

Private Sub RecuperarRegiones(sender As Object, e As EventArgs)

    Me.listaRegiones = Obtregiones()

End Sub

 

Private Sub CargarDropDownList1(ar As IAsyncResult)

  Me.ehRecuperarDatosDeDropDownList1.EndInvoke(ar)

  Me.dd_regiones.DataSource = Me.listaRegiones

  Me.dd_regiones.DataBind()

End Sub

 

Public Function Obtregiones() As List(Of Region)

   System.Threading.Thread.Sleep(3000)

   Dim regiones As New List(Of Region)

   regiones.Add(New Region With {.id = 1, .nombre = "Primera Region"})

   regiones.Add(New Region With {.id = 2, .nombre = "Segunda Region"})

   regiones.Add(New Region With {.id = 3, .nombre = "Tercera Region"})

   regiones.Add(New Region With {.id = 4, .nombre = "Cuarta Region"})

   regiones.Add(New Region With {.id = 5, .nombre = "Quinta Region"})

   Return regiones

 End Function

#End Region

 

#Region "dd_ciudades"

 Private Function RecuperarDatosDeDropDownList2(sender As Object, e As EventArgs, cb As AsyncCallback, state As Object) As IAsyncResult

 

   Me.ehRecuperarDatosDeDropDownList2 = New EventHandler(AddressOf Me.RecuperarCiudades)

   Return Me.ehRecuperarDatosDeDropDownList2.BeginInvoke(Me,
    EventArgs
.Empty, cb, Nothing)

 End Function

 

Private Sub RecuperarCiudades(sender As Object, e As EventArgs)

        Me.listaCiudades = Obtciudades()

End Sub

 

Private Sub CargarDropDownList2(ar As IAsyncResult)

  Me.ehRecuperarDatosDeDropDownList2.EndInvoke(ar)

  Me.dd_ciudades.DataSource = Me.listaCiudades

  Me.dd_ciudades.DataBind()

End Sub

 

Public Function Obtciudades() As List(Of Ciudad)

  System.Threading.Thread.Sleep(3000)

  Dim ciudades As New List(Of Ciudad)

  ciudades.Add(New Ciudad With {.id = 1, .nombre = "Concepcion"})

  ciudades.Add(New Ciudad With {.id = 2, .nombre = "Santiago"})

  ciudades.Add(New Ciudad With {.id = 3, .nombre = "Viña del Mar"})

  ciudades.Add(New Ciudad With {.id = 4, .nombre = "Puerto Montt"})

  ciudades.Add(New Ciudad With {.id = 5, .nombre = "Cañete"})

  Return ciudades

End Function

#End Region

 

End Class

 

Ciertamente el código puede resultar confuso,(adjunto el código fuente, ya que se ve mejor en Visual Studio que en el blog), primero se registran las “tareas” que vamos a correr en paralelo, cada tarea tiene un método de inicio(BeginEventHandler), y método de finalización (EndEventHandler), luego registramos cada una de estas tareas, en este caso son dos, lo hacemos llamando al método RegisterAsyncTask de la página.

Los métodos ObtCiudades y ObtieneRegiones no sufren alteraciones, ahora al momento de ejecutar la página, obtenemos mejores tiempo, tal cual habíamos estimado, 3,16 segundos.

image

Claro está que solo estoy usando esta funcionalidad con dos métodos, puedes utilizarlos con más según tu conveniencia.

Puedes bajar el código desde acá

image

Espero que te sirva!
@chalalo

Posted: 16/1/2012 20:41 por Gonzalo Perez | con 2 comment(s)
Archivado en: ,
Comparte este post:

Comentarios

MVP Factor ha opinado:

Agenda 24 enero, 2012 Sharing the Poing, South America 2012 Evento en Latinoamérica sobre SharePoint

# January 24, 2012 4:32 PM

MVP Factor ha opinado:

Agenda 24 enero, 2012 Sharing the Poing, South America 2012 Evento en Latinoamérica sobre SharePoint

# January 24, 2012 4:32 PM