Question

J'ai un site web asp.net (mvc). Comme la partie des fonctions que je vais devoir soutenir certaines opérations à long en cours d'exécution, par exemple:

Initié de l'utilisateur: L'utilisateur peut télécharger le fichier (XML) au serveur. Sur le serveur que je dois extraire le fichier, faire quelques manipulations (insérer dans le db) etc ... Cela peut prendre une minute à dix minutes (ou encore plus - dépend de la taille du fichier). Bien sûr, je ne veux pas bloquer la demande lorsque l'importation est en cours d'exécution, mais je veux rediriger l'utilisateur vers une page progrès où il aura la chance de voir l'état, des erreurs ou même annuler l'importation.

Cette opération ne sera pas fréquemment utilisé, mais il peut arriver que deux utilisateurs en même temps essaieront d'importer les données. Il serait agréable de courir les importations en parallèle. Au début, je pensais créer un nouveau thread dans le iis (action du contrôleur) et exécuter l'importation dans un nouveau thread. Mais je ne suis pas sûr que ce soit une bonne idée (pour créer des threads de travail sur un serveur Web). Dois-je utiliser les services Windows ou toute autre approche?

Initié par le système: - Je vais devoir mettre à jour périodiquement l'index de Lucene avec les nouvelles données. -. Je vais devoir envoyer des e-mails de masse (à l'avenir)

Dois-je mettre en œuvre cela comme un emploi dans le site et exécuter le travail via Quartz.net ou devrais-je créer un service de fenêtres ou quelque chose?

Quelles sont les meilleures pratiques en matière de fonctionnement site « emplois »?

Merci!

Était-ce utile?

La solution

Je mettre en œuvre les fenêtres service autonome pendant de longues tâches en cours d'exécution. application Web délégués tâches en cours d'exécution longue à ce service via l'approche de file d'attente. Il est à vous comment vous allez organiser la file d'attente des tâches. Est-ce que la file d'attente de travail ont la priorité, le temps d'exécution maximal ou non. File d'attente peut être mis en œuvre comme table ordinaire (s) dans un SGBD, qui contient des propriétés d'information d'état d'exécution du travail (approche assez simple).

scénario Alors commun peut regarder ce qui suit:

  • Le client envoie toutes les informations nécessaires à serveur web

  • délégués Web serveur tâche au service et informe le client - tâche était mis en attente avec succès (ID de tâche est envoyée au client aussi)

  • démarrage du service externe tâche de traitement, la mise à jour des informations de progression.

  • Client démarre le serveur web de vote avec exécution courte demande au sujet de l'emploi (avec l'ID reçu plus tôt) état d'avancement.

Vous pouvez choisir différentes technologies (service Windows + DB / service WCF) et les différentes approches de communication (sondages, pousser, callbacks) mais je conseille de déléguer des tâches de longue durée au service externe (ne pas les exécuter dans l'application Web).

L'exécution des tâches en cours d'exécution à long apporte le modèle thread par demande (en termes de programmation multithread). Ce modèle a une mauvaise évolutivité et pool de threads nombre maximum de limitations de fils. Ce n'est pas votre cas si :)

Autres conseils

À mon avis longue tâches en cours d'exécution devraient généralement toujours être déléguées à des opérations non basées sur l'interface utilisateur. Je suggère peut-être un service WF ou une fenêtre.

J'ai mis en place avec succès un scénario similaire à celui en utilisant jQuery. En fait, j'utiliser la beforeSend: fonction pour afficher la page de type 's'il vous plaît attendre. voici le code de base en jeu (altso je ne sais pas, vous pouvez également utiliser la classe de base de AsyncController pour faire le async d'action):

<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>

espérons que cette aide.

la méthode SendAjax est purement une fonction d'emballage pour rendre les choses un peu plus cohérente. Ici, il est en pleine:

<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>

[modifier] - pas sûr de ce qui se passe avec la mise en forme SendAjax. espérons qu'il est facile de copier / coller sur ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top