2010-05-11 12 views
10

Tengo un sitio web asp.net (mvc). Como parte de las funciones que tendrá que soportar algunas operaciones de larga ejecución, por ejemplo:Operaciones de larga ejecución (hilos) en un entorno web (asp.net)

inicia a partir de usuario: El usuario puede cargar (XML) presentar al servidor. En el servidor necesito extraer el archivo, hacer algo de manipulación (insertar en el db), etc. Esto puede llevar de un minuto a diez minutos (o incluso más, depende del tamaño del archivo). Por supuesto, no quiero bloquear la solicitud cuando se está ejecutando la importación, pero quiero redirigir al usuario a alguna página de progreso donde tendrá la oportunidad de ver el estado, errores o incluso cancelar la importación.

Esta operación no se usará con frecuencia, pero puede suceder que dos usuarios al mismo tiempo intenten importar los datos. Sería bueno ejecutar las importaciones en paralelo. Al principio estaba pensando en crear un nuevo hilo en el iis (acción del controlador) y ejecutar la importación en un nuevo hilo. Pero no estoy seguro si esta es una buena idea (para crear hilos de trabajo en un servidor web). ¿Debo usar servicios de Windows o cualquier otro enfoque?

Iniciado desde el sistema: - Tendré que actualizar periódicamente el índice de lucene con los datos nuevos. - Tendré que enviar correos masivos (en el futuro).

¿Debería implementar esto como un trabajo en el sitio y ejecutar el trabajo a través de Quartz.net o debería también crear un servicio de Windows o algo así?

¿Cuáles son las mejores prácticas cuando se trata de ejecutar "trabajos" del sitio?

Gracias!

+0

Considere algunas de estas respuestas en una pregunta relacionada http://stackoverflow.com/a/41734936/56145 –

Respuesta

6

Implementaré un servicio de Windows autónomo para tareas de larga ejecución. La aplicación web delega tareas de larga ejecución a este servicio a través del enfoque de cola. Depende de usted cómo organizará las tareas en cola. La tarea en cola tendrá prioridad, el tiempo máximo de ejecución o no. Cola puede implementarse como tabla (s) ordinaria (s) en DBMS, que contiene propiedades de información de estado de ejecución de trabajo (enfoque bastante directo).

escenario tan común puede parecer el siguiente:

  • cliente envía toda la información requerida al servidor web

  • tarea delegados servidor web para dar servicio a y notifica cliente - tarea se cola correctamente (la identificación de la tarea también se envía al cliente)

  • El servicio externo inicia el procesamiento de la tarea, actualiza la información del progreso norte.

  • El cliente inicia el sondeo del servidor web con peticiones de ejecución cortas sobre el trabajo (con id recibido anteriormente) estado y progreso.

Puede elegir diferentes tecnologías (Windows Service + DB/Servicio WCF) y diferentes enfoques de comunicación (sondeo, empujar, devoluciones de llamada) pero yo aconsejaría a delegar tareas de larga duración a un servicio externo (no realizarlas dentro web aplicación).

La ejecución de tareas de ejecución larga trae el modelo de hilos por solicitud (en términos de programación multiproceso). Este modelo tiene escasa escalabilidad y un número de subprocesos máximo de limitaciones de subprocesos. No es tu caso, sin embargo :)

+0

Solía ​​hacer grandes conversiones, generaciones de informes, generaciones de datos en tal manera. Esta es la única opción lógica. –

4

En mi opinión, las tareas de ejecución prolongada siempre deben delegarse en operaciones que no se basan en la interfaz de usuario. Sugeriría quizás un servicio de WF o de ventana.

1

He implementado con éxito un escenario similar a este usando jQuery. Básicamente, utilizo la función beforeSend: para mostrar la página de tipo 'espere por favor'. aquí está el código básico en juego (altso no lo hago, también se puede utilizar la clase AsyncController de base para que la acción asíncrona):

<script type="text/javascript"> 
    $(document).ready(function() { 
     $('#create').bind('click', function() { 
      saveFundProperty(); 
     }); 
    }); 

    // main functions 
    function saveFundProperty() { 
     var url = '<%= Url.Action("Create", "FundProperty") %>'; 
     var params = { fundId: $("#FundID").val(), propertyId: $("#PropertyID").val() }; 
     SendAjax(url, params, beforeQuery, saveFundPropertyResponse); 
    } 

    function beforeQuery() { 
     var url = '<%= Url.Action("Wait", "FundProperty") %>'; 
     $("#statusMsg").load(url); 
    } 

    function saveFundPropertyResponse(data) { 
     if (data.length != 0) { 
      if (data.indexOf("ERROR:") >= 0) { 
       $("#statusMsg").html(data).css('backgroundColor','#eeaa00'); 
      } 
      else { 
       $("#statusMsg").html(data); 
      } 
     } 
    } 
</script> 

esperanza esto ayuda.

el método SendAjax es puramente una función de envoltura para hacer las cosas un poco más consistentes. aquí es en su totalidad:

<script type="text/javascript"> 
function SendAjax(urlMethod, jsonData, beforeSendFunction, returnFunction, dataType, contentType) { 
    $.ajaxSetup({ cache: false }); 
    dataType = dataType || "text"; // default return type 
    contentType = contentType || "application/x-www-form-urlencoded"; // default input type 
    $.ajax({ 
     type: "POST", 
     url: urlMethod, 
     data: jsonData, 
     dataType: dataType, 
     contentType: contentType, 
     beforeSend: function() { 
      if(beforeSendFunction!==null) 
       beforeSendFunction(); 
     }, 
     success: function(data) { 
      // Do something interesting here. 
      if (data != null && returnFunction!==null) { 
       returnFunction(data); 
      } 
     }, 
     error: function(xhr, status, error) { 
      // Boil the ASP.NET AJAX error down to JSON. 
      var err = eval("(" + xhr.responseText + ")"); 

      // Display the specific error raised by the server 
      alert(err.Message); 
     } 
    }); 
} 
</script> 

[editar] - no está seguro de lo que está pasando con el formato SendAjax. Espero que sea fácil de copiar/pegar ...

Cuestiones relacionadas