D'abord, quelques réflexions de fond:
1) Comme il est un travail de longue haleine en cours d'exécution, vous pouvez un cache d'emplois précédemment exécutés de sorte que vous ne dupliquez pas le travail et surchargeant votre serveur.
2) Vous ne devriez pas avoir à démarrer un thread d'arrière-plan séparé, puisque chaque requête ASP.NET va être en cours d'exécution dans son propre thread. Toutefois, si vous trouvez que vous êtes affamé votre processus de travail ASP.NET, vous pouvez rendre vos méthodes Web asynchrones côté serveur - voir: this article.
L'implémentation nécessite trois composants: un cache, une méthode Web pour exécuter le travail et une méthode Web pour vérifier l'état du travail. Vous devrez également être en mesure de générer une clé permettant au système de suivre les demandes. Vous pouvez générer ce côté serveur (lorsque vous générez la page), ou côté client (si vous avez un algorithme intelligent qui peut générer des identifiants uniques).
Le cache peut être défini sur une application si vous souhaitez que les utilisateurs puissent partager des travaux en cours d'exécution ou que la portée soit limitée. Le cache est simplement un dictionnaire contenant des références à vos instances de travail en cours d'exécution.
Un exemple simple (ceci ne compilera pas, contient probablement des erreurs de syntaxe, et est principalement destiné à faire passer le point).
serveur pseudo-code:
//In application Session_Start,
Session["ReportCache"] = new Dictionary<string, ReportStatus>();
public class ReportResults
{
}
public class ReportStatus
{
public int PercentComplete = 0;
}
[WebMethod(EnableSessions = true)]
ReportResults RunReport(string uniqueid)
{
ReportStatus status = new ReportStatus();
Session["ReportStatus"].Add(uniqueid, status);
//Start report
for(int i = 0; i < 100000; ++i)
{
//update the report status
status.PercentComplete = 100 * 100000 * i/100000;
}
Session["ReportStatus"].Remove(uniqueid);
}
[WebMethod(EnableSessions=true)]
public ReportStatus GetStatus(uniqueid)
{
try
{
return Session["ReportStatus"][uniqueid];
}
catch(Exception)
{
return null;
}
}
Sur le client, utilisez ajax pour appeler la première méthode Web. Il n'appelle pas le rappel onSuccess tant que le rapport n'est pas terminé.Utilisez setTimeout pour interroger périodiquement la seconde méthode Web pour obtenir des informations d'état et mettre à jour le client. Lorsque la première méthode Web est terminée, annulez votre minuterie.
Votre plus gros problème sera le fait que votre serveur exécutera de nombreux travaux de longue durée, ce qui peut dégrader les performances globales et la réactivité. Vous pourriez vouloir adopter une approche complètement différente. Par exemple, plutôt que d'exécuter les rapports à la demande par utilisateur, vous pouvez mettre en file d'attente la liste des personnes souhaitant recevoir le rapport. Une fois par heure, par jour et par semaine, vous pouvez exécuter un rapport distinct. et l'envoyer.
Etes-vous en train d'implémenter un indicateur de progression sur le client pendant que le serveur est en train de croquer le rapport? Je veux m'assurer de comprendre la question avant de tenter de décrire la solution :). –
Oui, essentiellement mon bouton "Générer des rapports" utiliserait AJAX pour appeler une méthode Web pour démarrer le processus, alors je voudrais interroger le serveur toutes les secondes ou deux pour voir ce que la progression est. Si je compte jusqu'à 10 millions et que je stocke chaque résultat dans une variable, ma fonction d'interrogation AJAX devrait être capable de récupérer la valeur actuelle. –