Pour effectuer cela, nous utiliserons les threads (System.threading) et les extensions AJAX de Microsoft.
Avant de débuter certaines contditions sont requises. L'action longue doit être inégrée a une classe, on doit pouvoir la lancer de cette manière
MonObjet.tacheLongue();
Il faudra pour suivre l'avancement de la tache que la classe possède un attribut public contenant un message qui donne l'état de la tache.
private String messageEtat;
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="messageLabel" runat="server">asp:Label><br /> <asp:HyperLink ID="actionLink" runat="server" Target="_blank" Visible="False" Text="Telecharger le fichier généré">asp:HyperLink><br /> <asp:Timer ID="Timer1" runat="server" Enabled="false" Interval="25" OnTick="Timer1_Tick">asp:Timer> <ContentTemplate><asp:UpdatePanel>
L'update panel contient un Label pour le message de statut et un HyperLink placé ici pour montrer qu'il est possible d'ajouter d'autres controles qui seront modifiés selon l'état de la tache. Notez aussi la présence du timer qui s'occupera de rafraichir le panel a intervalle réguliers.
Occupons nous maintenant de la fonction Timer1_Tick
/// <summary>
/// Timer sur le update panel AJAX / Multithread
/// Permet d'afficher le statut de la tache lancée en fond
/// </summary>
protected void Timer1_Tick (object sender, EventArgs e)
{
classeLongue longTask = (classeLongue)Session ["longTask"];
if (longTask!= null) {
messageLabel.Text = longTask.Message;
if (longTask.Message.Contains ("ok")) { //L'import est réussi
messageLabel.Visible = false;
actionLink.Visible = true;
Session ["longTask"] = null;
Timer1.Enabled = false;
}
Pour ne pas perdre la tache de fond entre les postback et autres changements de page, il faudra la conserver dans une variable Session. Je ne sais pas ceci reflète la meilleure pratique mais c'est la méthode que j'utilise dans mes applications ASP.NET et elle fonctionne bien. La première étape consiste donc a récupérer l'objet que nous avons stocké dans une variable de session. S'il existe, nous affichons le message longTask.Message sur le label prévu a cet effet. La fonction pourait s'arréter ici, mais nous allons prendre en charge la fin de la tache, signalé dans l'exemple par le message "ok". Celui ci provoque le l'affichage de l'HyperLink et le masquage du Label de statut.L'objet contenant la tache a executer peut être supprimé et le timer arrété.
Il ne reste plus maintenant qu'a écrire l'évènement qui va lancer la tache :
protected void launchTask_Click (object sender, EventArgs e)
classeLongue longTask = new classeLongue ();
longTask.IdUser = Convert.ToInt32 (HttpContext.Current.Session ["IdUser"]);
longTask.SavePath = HttpContext.Current.Server.MapPath ("saveDirectory");
Thread taskThread = new Thread (new ThreadStart (longTask.runLongTask));
taskThread.Start ();
Session ["longTask"] = (classeLongue)longTask;
Timer1.Enabled = true;
messageLabel.Visible = true;
Dans l'exemple ci dessus, on montre bien que les variables de type Session et Server sont envoyées a l'objet avant de lancer la tache. L'objet longTask est stocké en session pour pouvoir le récupérer par la suite et le timer est démarré.
Voila nous avons lancé notre tache dans un nouveau thread. Au final, le plus dur doit être de bien isoler la tache de fond dans une classe indépendante.