2009-12-04 8 views
9

J'essaie d'afficher de manière asynchrone des données dans des panneaux de mise à jour sur un site Web où les tâches de récupération de données prennent des durées différentes. Je voudrais mettre à jour chaque panneau pour montrer les données sur la page après chaque tâche se termine. Cependant, peu importe ce que j'essaie, tous les panneaux de mise à jour changent de contenu après la fin de la dernière tâche.ASP.Net: Panneau de mise à jour asynchrone Chargement avec deux panneaux de mise à jour

Par exemple:

J'ai deux tâches:

  • Celui qui tente de mettre à jour une étiquette UpdatePanel1 après 5 secondes
  • Celui qui tente de mettre à jour une étiquette dans UpdatePanel2 après 10 secondes

Le résultat attendu est de hav Seule l'étiquette dans UpdatePanel1 change après 5 secondes, cependant, les deux panneaux de mise à jour se mettent à jour en même temps, à 10 secondes.

Les deux panneaux de mise à jour sont définis sur updatemode = "Conditionnel" et ils sont invités à effectuer une publication depuis le client javascript. Voici une liste complète de l'exemple ci-dessus.

Qu'est-ce qui me manque ici? Comment puis-je charger un panneau de mise à jour, puis l'autre, exécuter les deux tâches de manière asynchrone?

Merci,

TM

ASPX:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" 
    Inherits="_Default"%> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
</head> 
<body onload="partialPostback();"> 
    <script language="JavaScript" type="text/javascript"> 

    function partialPostback() { 
     __doPostBack('UpdatePanel1', ''); 
     __doPostBack('UpdatePanel2', ''); 
    } 
    </script> 

    <form id="form1" runat="server"> 
     <asp:ScriptManager ID="ScriptManager1" runat="server"/> 

     5 sec: 
     <asp:UpdatePanel ID="UpdatePanel1" runat="server" 
     UpdateMode="Conditional" OnLoad="UpdatePanel1_Load"> 
      <ContentTemplate> 
       <asp:Label ID="Label2" runat="server" Text="Label"/><br /> 
      </ContentTemplate> 
     </asp:UpdatePanel><br /> 

     10 sec: 
     <asp:UpdatePanel ID="UpdatePanel2" runat="server" 
     UpdateMode="Conditional" OnLoad="UpdatePanel2_Load"> 
      <ContentTemplate> 
       <asp:Label ID="Label1" runat="server" Text="Label"/><br /> 
      </ContentTemplate> 
     </asp:UpdatePanel> 
    </form> 
</body> 
</html> 

C#:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Threading; 

public partial class _Default : System.Web.UI.Page 
{ 
    Thread t1; 
    Thread t2; 

    protected override void OnPreRender(EventArgs e) 
    { 
     if (t1 != null) 
     { t1.Join(); } 

     if (t2 != null) 
     { t2.Join(); } 

     base.OnPreRender(e); 
    } 

    protected void Page_Load(object sender, EventArgs e) 
    { } 

    protected void UpdatePanel1_Load(object sender, EventArgs e) 
    { 
     if (IsPostBack) 
     { 
      ThreadStart tstart = new ThreadStart(DoWork1); 
      t1 = new Thread(tstart); 
      t1.IsBackground = true; 
      t1.Start(); 
     } 
    } 

    protected void UpdatePanel2_Load(object sender, EventArgs e) 
    { 
     if (IsPostBack) 
     { 
      ThreadStart tstart = new ThreadStart(DoWork2); 
      t2 = new Thread(tstart); 
      t2.IsBackground = true; 
      t2.Start(); 
     } 
    } 

    private void DoWork1() 
    { 
     Thread.Sleep(5000); 
     this.Label2.Text = "Done in 5 sec!"; 
     this.UpdatePanel1.Update(); 
    } 

    private void DoWork2() 
    { 
     Thread.Sleep(10000); 
     this.Label1.Text = "Done in 10 sec!"; 
     this.UpdatePanel2.Update(); 
    } 
} 

Répondre

0

Je soupçonne que vous n'êtes pas appeler cela comme de manière asynchrone que vous pensez b/c des jointures de fil. Il semblerait que vous disiez simplement bloquer OnPrerender jusqu'à ce que le thread 2 se termine. Parce que les deux appels 1 et 2 sont appelés à partir de la même méthode, vous êtes bloqués jusqu'à ce que les deux soient terminés. Si vous insérez des écritures pour voir quand les choses sont appelées, il pourrait devenir un peu plus facile de voir ce qui se passe.

Je soupçonne également que le texte sur 1 ne sera pas vraiment mis à jour jusqu'à ce que prerender soit complet de ce que je sais. ASP.NET traditionnel, rien n'est renvoyé au client jusqu'à après prerender terminé. Mais je ne sais pas grand-chose sur le panneau de mise à jour, donc je pourrais parler des indésirables sur celui-là et anticiper être marqué ...

0

Les jointures dans votre gestionnaire de pré-rendu empêchent le rendu de revenir au client . Au lieu de ce que vous avez, je pense que vous pourriez faire quelque chose comme ceci:

if (t1 != null) { 
    t1.join(); 
} else if (t2 != null) { 
    t2.join(); 
} 

Ce code a l'effet secondaire malheureux d'être dépendant de savoir quel fil sera de retour en premier lieu, cependant.

Cependant, si vous essayez simplement de comprendre comment envoyer des événements du serveur au client (et html 5 est une option), je vous recommande de regarder dans server-sent events (ou des sockets web si vous avez besoin d'une communication full duplex).Si html 5 n'est pas une option, je crois que vous pouvez utiliser des hacks javascript pour simuler des sockets web. Vous pouvez lire sur certains de ces here et here.

modifier: quelques liens pour non-html 5 alternatives

0

Êtes-vous capable d'utiliser 4,5 .NET ou êtes-vous limités à des versions antérieures? v4.5 a beaucoup de nouvelles fonctionnalités qui rendent la création de méthodes asynchrones assez simple sans avoir à se soucier de la gestion des threads. Ce lien a une bonne explication de la façon de mettre en œuvre une méthode asynchrone avec la nouvelle tâche Task et async/await opérateurs: Working with Asynchronous Operations in ASP.NET 4.5 Web Forms

Essentiellement, vous aurait tout simplement avoir à créer un Task pour chaque méthode responsable de la mise à jour du UpdatePanel et faire feu sur le chargement de la page. À la fin de chaque tâche pourrait dormir pendant 5 ou 10 secondes avant de s'appeler pour vous donner l'effet que vous recherchez.

0

Au lieu de cela vous pouvez utiliser 2 commandes de minuterie, l'un avec un intervalle de 5000 et un autre avec un intervalle de 10000

1

Il suffit de mettre une étiquette de déclenchement à l'intérieur de chaque UpdatePanel pointant vers un asp: minuterie et l'intervalle réglé sur 5000 et 10000 millisecondes.

ci-dessous est la solution que vous demandez, en utilisant UpdatePanel, mais prenez soin parce que chaque 5 et 10 secondes il y a un feu pour PostBack Timer:

Je recommande d'utiliser de javascript ou jQuery pour éviter postbacks.

ASPX:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 
    Inherits="WebApplication1.Default" %> 
<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head id="Head1" runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
     <asp:ScriptManager ID="ScriptManager1" runat="server"/> 

     5 sec: 
     <asp:UpdatePanel ID="UpdatePanel1" runat="server"> 
      <Triggers> 
       <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick"/> 
      </Triggers> 
      <ContentTemplate> 
       <asp:Label ID="Label2" runat="server" Text="Label"/><br /> 
      </ContentTemplate> 
     </asp:UpdatePanel> 
     <asp:Timer ID="Timer1" runat="server" Interval="5000" 
      OnTick="Timer1_Tick"/><br /> 

     10 sec: 
     <asp:UpdatePanel ID="UpdatePanel2" runat="server"> 
      <Triggers> 
       <asp:AsyncPostBackTrigger ControlID="Timer2" EventName="Tick"/> 
      </Triggers> 
      <ContentTemplate> 
       <asp:Label ID="Label1" runat="server" Text="Label"/><br /> 
      </ContentTemplate> 
     </asp:UpdatePanel> 
     <asp:Timer ID="Timer2" runat="server" Interval="10000" 
      OnTick="Timer2_Tick"/> 
    </form> 
</body> 
</html> 

C#

using System; 

namespace WebApplication1 
{ 
    public partial class Default : System.Web.UI.Page 
    { 
     protected void Timer1_Tick(object sender, EventArgs e) 
     { 
      this.Label2.Text = "Done in 5 sec!"; 
     } 

     protected void Timer2_Tick(object sender, EventArgs e) 
     { 
      this.Label1.Text = "Done in 10 sec!"; 
     } 
    } 
} 
Questions connexes