Ejecutar una función lenta en una página asp.net

Preguntado hace 1 año

Guillermo Barrios
Votos
PositivosNegativosTotal
1 0 1
99 Visualizaciones
Compártelo: Compártelo en twitterCompártelo en Facebook

Hola, tengo una página a la que se llama cada hora y que ejecuta una serie de funciones, por lo general funciona bien, pero de vez en cuando da un error de time out (Request timed out.). La página en realidad no se sirve a los usuarios, sólo sirve para ejecutar esas funciones. Me pregunto si hay una manera de que al ejecutar esas funciones, la página siga su trabajo y se devuelva el html independientemente de que se sigan ejecutando las funciones y así que estas tarden lo que tengan que tardar.

Saludos.

Actualizando datos

3 Respuestas

Hace 1 año

Buck

Buck

751Distinciones de plata1Distinciones de bronce3
Votos
PositivosNegativosTotal
202

Creo que Rafa tiene razon. Con hilos lo podrias hacer. Mira este ejemplo

        protected void Button1_Click(object sender, EventArgs e)
        {
            Thread worker = new Thread(new ParameterizedThreadStart(HeavyOperation));
            worker.IsBackground = false;
            worker.Start(DateTime.Now);
        }

        public void HeavyOperation(Object obj)
        {
            Thread.Sleep(10000);
            File.WriteAllText("C:\\Temp.txt", String.Format("Termine la ejecucion en: {0}", (DateTime)obj));
        }

Es importante lo siguiente:

worker.IsBackground = false;

Si fuera background el hilo principal moriria en cuanto la pagina devolviese el resultado y con el el hilo secundario. De esta forma el hilo principal devolvera la pagina al usuario inmediatamente pero no morira hasta que el hilo secundario termine.

public void HeavyOperation(Object obj)

Esta es la firma estandar para un delegado, es decir, tu funcion "pesada" debe se void NombreDeFuncion (Object param). Si tienes mas 1 parametro los puedes meter a todos en un array y pasar ese array.

File.WriteAllText("C:\\Temp.txt", String.Format("Termine la ejecucion en: {0}", (DateTime)obj));

Si vas a ejecutar mi ejemplo cerciorate de que el usuario asp.net tiene permisos de escritura en la ubicacion donde vas a escribir el fichero.

Dime si te funciona

Saludos

Cerrar

No estoy seguro de que ese comportamiento sea tal como dices, poner el Thread como IsBackground = false no te asegura nada sobre la ejecución de ASP.NET ni de IIS, sino solo de ese thread. Pero si ese tipo de comportamiento es el que se quiere, quizá sea suficiente con hacer páginas asíncronas, donde ASP.NET ayuda con un atributo en la propia página, tal como se explica en este artículo: http://msdn.microsoft.com/en-us/magazine/cc163725.aspx Esto si está integrado en el flujo de las páginas con lo que te aseguras el no tener sorpresas... Alejandro Mezcua hace 1 año
isBackground=false hace que el proceso de asp.net no termine hasta que el thread haya terminado. http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx Buck hace 1 año
Pero este método no te va devolviendo respuesta al navegador de la ejecución y nadie te asegura de que IIS no vaya a reciclar el proceso mientras esté en ejecución ¿no? Alejandro Mezcua hace 1 año
Funciona! Efectivamente la página se devuelve y el hilo sigue a su rollo. Muchas gracias. Guillermo Barrios hace 1 año

Hace 1 año

Alejandro Mezcua
Votos
PositivosNegativosTotal
202

Puedes variar el timeout de asp.net siguiendo estos pasos: http://weblogs.asp.net/aghausman/archive/2009/02/20/prevent-request-timeout-in-asp-net.aspx

pero ten en cuenta que eso te cambia el timeout de toda la aplicación, no solo de esa página.

De todas formas ¿por qué estás usando ese mecanismo para realizar tareas automatizadas? Yo te recomendaría utilizar el gestor de tareas automatizadas de windows (Task Scheduler), en lugar de un servidor web para esas cosas.

Cerrar

Me decanto por la opción de Antonio, me parece la más sencilla. De todos modos, gracias. Guillermo Barrios hace 1 año
Otra opción que puedes probar es crear algo estilo Comet, donde dejas la conexión HTTP abierta para que el servidor vaya respondiendo según tenga datos, pero has de tener cuidado con esto ya que puedes dejar al servidor sin threads para responder a nuevas peticiones... http://www.codeproject.com/KB/aspnet/CometAsync.aspx Alejandro Mezcua hace 1 año
¿Sólo tienes una aplicación ASP.NET? ¿Puedes montar más? Si puedes montar una segunda aplicación podrías variar el timeout en esta segunda, mover tu lógica a esa y dejar la otra como esté. Pero ten en cuenta que ni ASP.NET ni IIS están diseñados para ese tipo de operaciones con lo que aunque arregles el timeout de ASP.NET puedes encontrarte con otros problemas, como timeout de navegador etc.. Alejandro Mezcua hace 1 año
Hola, Alejandro uso esa opción porque es un hosting y no me dejan otra :S Lo del timeout cambiarlo para todos no acabo de verlo, ¿hay alguna manera de que no se quede a la espera de terminar algo, que lance la función pero que no espere? Saludos y muchas gracias :) Guillermo Barrios hace 1 año

Hace 1 año

Rafa

Rafa

1mDistinciones de plata2Distinciones de bronce8
Votos
PositivosNegativosTotal
202

No sé como se hará eso en .net, pero supongo que se podría solucionar haciemdo que la pagina cree unos hilos (o incluso procesos) independientes y los lanze, y después escriba el html. Eso sí, perderías todo posible control de si las tareas se terminan o de su resultado.

Cerrar

Gracias, al final se la he puesto a Antonio como correcta porque ponía el código, pero he votado + esta como origen de la otra. Guillermo Barrios hace 1 año

Tu respuesta

Confirmación

Cerrar

Si sales ahora, perderás los cambios. ¿Estás seguro de querer salir?

Para participar en Babelias, debes estar convenientemente validado. Si ya eres usuario inicia sesión, si no lo eres, te puedes registrar.

Dar una respuesta

Trata de ser descriptivo, usa al menos 25 caracteres