2011-07-20 4 views
1

Je suis perplexe. J'essaie d'afficher une barre de progression pendant que mon site exécute une requête. La requête prend de 4 à 6 minutes. Ma barre de progression tire sa valeur de la base de données, Oracle a une requête intégrée pour fournir les valeurs à la barre de progression. J'utilise EssentialObjects' ProgressBar. En fait, je viens de mettre en "valeur" à un nombre entier compris entre 1 et 100.Comment mettre à jour une page pendant une publication asynchrone?

Voici une version simplifiée de mon code:

Page:

<asp:UpdatePanel ID="upQuery" runat="server"> 
    <ContentTemplate> 
     <asp:Button ID="btnExecute" runat="server" OnClick="btnExecute_Click" /> 
    </ContentTemplate> 
</asp:UpdatePanel> 
<asp:UpdatePanel ID="upProgress" runat="server"> 
    <ContentTemplate> 
     <asp:Timer ID="tmr" runat="server" Enabled="false" 
        OnTick="tmr_Tick" Interval="3000"></asp:Timer> 
     <eo:ProgressBar ID="pbr" runat="server" ></eo:ProgressBar> 
    </ContentTemplate> 
</asp:UpdatePanel> 

code:

protected void btnExecute_Click(object sender, EventArgs e) { 
     tmr.Enabled = true; 
     ExecuteLongQuery(); 
} 

protected void tmr_Tick(object sender, EventArgs e) { 
     pbr.Value = GetProgress(); 
} 

Fondamentalement, lorsque je clique sur btnExecute, la minuterie ne démarre pas tant que la publication n'est pas terminée, ce qui fait que la barre de progression ne s'affiche jamais. J'ai essayé un rappel, pas sûr si je l'ai fait correctement, mais la page ne montrerait pas le résultat pendant la publication. Comment est-ce que j'obtiens le temporisateur (ou n'importe quoi) pour répondre pendant que la page est dans la publication asynchrone?

+1

Vous devez donner plus d'informations sur les threads et plus de code. L'idée est, soit vous vous abonnez à l'événement ProgressChanged de votre requête/classe ou à l'intérieur de la classe, invoquez l'interface utilisateur, mais dans les deux sens, pour aider, nous avons besoin de voir plus de code. –

+0

Ceci est une page Web, pas un formulaire Windows. Il n'y a pas d'événement ProgressChanged, car j'utilise un contrôle personnalisé. Je ne sais pas quoi d'autre je dois fournir .. – tedski

+1

Le code pour ExecuteLongQuery() serait utile ... –

Répondre

3

Le fait que vous avez activé le temporisateur n'est pas transmis au client tant que la publication n'est pas terminée. C'est juste comment ça fonctionne. L'exécution de code sur le serveur n'a pas d'effet immédiat sur le client. Si vous attendez ExecuteLongQuery() pour terminer avant d'envoyer la réponse au client, vous ne verrez jamais de temporisateur.

Votre meilleur pari est probablement d'exécuter ExecuteLongQuery() dans un thread séparé sur le serveur, permettant la publication et l'ouverture du minuteur.

Je suggère de lire sur le cycle de vie de la page ASP.Net - this semble être un bon point de départ.

+0

Je suppose que j'avais l'impression que l'utilisation d'un UpdatePanel commencerait un autre thread, mais je suppose que ce n'est pas si facile . Je vais regarder dans le filetage. Y a-t-il un bon tutoriel pour ça? – tedski

+0

Ah, non. UpdatePanel effectue simplement une publication qui ne recharge qu'une partie de la page. Il ne retournera pas au client tant que tout le code du gestionnaire d'événements n'aura pas fini d'être exécuté. Je n'ai aucune expérience avec le filetage dans .Net mais je crois que vous auriez besoin d'utiliser un thread de travail, qui prend en charge ASP.Net. Google autour et vous devriez être en mesure de trouver un tutoriel assez facilement. Bonne chance! :) –

+0

Wow, c'était vraiment facile. Je viens d'utiliser [ce] tutoriel (http://www.sitepoint.com/threading-asp-net/). Merci! – tedski

5

J'ai trouvé ça et ça marche pour moi. Vous pouvez le changer selon vos besoins. Cela fonctionne pour chaque publication de page, et si vous voulez le restreindre, changez le code selon vos besoins.

<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head id="Head1" runat="server"> 
     <title></title> 
     <style type="text/css"> 
      .modalPopup 
      { 
       background-color: #696969; 
       filter: alpha(opacity=40); 
       opacity: 0.7; 
       xindex: -1; 
      } 
     </style> 
    </head> 
    <body> 
     <form id="form2" runat="server"> 
       <asp:ScriptManager ID="ScriptManager2" runat="server" /> 
       <script type="text/javascript"> 
        var prm = Sys.WebForms.PageRequestManager.getInstance(); 
        //Raised before processing of an asynchronous postback starts and the postback request is sent to the server. 
        prm.add_beginRequest(BeginRequestHandler); 
        // Raised after an asynchronous postback is finished and control has been returned to the browser. 
        prm.add_endRequest(EndRequestHandler); 
        function BeginRequestHandler(sender, args) 
        { 
         //Shows the modal popup - the update progress 
         var popup = $find('<%= modalPopup.ClientID %>'); 
         if (popup != null) 
         { 
          popup.show(); 
         } 
        } 

        function EndRequestHandler(sender, args) 
        { 
         //Hide the modal popup - the update progress 
         var popup = $find('<%= modalPopup.ClientID %>'); 
         if (popup != null) 
         { 
          popup.hide(); 
         } 
        } 
       </script> 
       <div> 
        <asp:UpdateProgress ID="UpdateProgress1" runat="server"> 
         <ProgressTemplate> 
          <asp:Image ID="Image1" ImageUrl="waiting.gif" AlternateText="Processing" runat="server" /> 
         </ProgressTemplate> 
        </asp:UpdateProgress> 
        <ajaxtoolkit:modalpopupextender id="modalPopup" runat="server" targetcontrolid="UpdateProgress" popupcontrolid="UpdateProgress" backgroundcssclass="modalPopup" /> 
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> 
         <ContentTemplate> 
          <asp:Button ID="Button1" runat="server" Text="Submit" OnClick="btnSubmit_Click" /> 
         </ContentTemplate> 
        </asp:UpdatePanel> 
      </div> 
     </form> 
    </body> 
</html> 
Questions connexes