2009-12-04 15 views
9

que estoy tratando de mostrar de forma asíncrona de datos en paneles de actualización en un sitio web donde las tareas de recuperación de datos tienen diferentes tiempos. Me gustaría actualizar cada panel para mostrar los datos en la página después de que termine cada tarea.ASP.Net: Panel de actualización asíncrona de carga con dos paneles de actualización

Sin embargo, no importa lo que intente, todos los paneles Actualizar cambiar su contenido después de la última tarea se ha completado.

Por ejemplo:

tengo dos tareas:

  • Uno que intenta actualizar una etiqueta en UpdatePanel1 después de 5 segundos
  • Uno que intenta actualizar una etiqueta en UpdatePanel2 después de 10 segundos

El resultado esperado es que hav Solo la etiqueta en UpdatePanel1 cambia después de 5 segundos; sin embargo, ambos paneles de actualización se actualizan al mismo tiempo, en 10 segundos.

Ambos paneles de actualización se ajustan a UpdateMode = "condicional" y se les dice que la devolución de datos desde JavaScript cliente. A continuación se encuentra una lista completa del ejemplo anterior.

¿Qué me falta aquí? ¿Cómo puedo cargar un panel de actualización, y luego el otro, haciendo que ambas tareas se ejecuten de forma asíncrona?

Gracias,

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(); 
    } 
} 

Respuesta

0

Sospecho que no está llamando a esto como forma asincrónica como usted piensa b/c del hilo se une. Parece que básicamente dices bloque OnPrerender hasta que el hilo 2 termina. Dado que tanto el 1 como el 2 están siendo llamados desde el mismo método, estará bloqueado hasta que ambos finalicen. Si agrega algunas líneas de escritura para ver cuándo se están llamando las cosas, podría ser un poco más fácil ver lo que está sucediendo.

también sospecho que el texto en 1 no será realmente actualizar hasta que se haya completado prerender por lo que sé. ASP.NET tradicional, no se devuelve nada al cliente hasta después de que prerender finalice. Pero no sé mucho sobre el panel de actualización, así que podría estar hablando basura sobre eso y anticipar que se marcó ...

0

Las uniones en su controlador de pre-render están bloqueando el procesamiento de volver al cliente . En lugar de lo que tiene, que sospecha que podría hacer algo como esto en su lugar:

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

Este código tiene el desafortunado efecto secundario de ser dependiente de saber cuál de ellos va a devolver en primer lugar, sin embargo.

Sin embargo, si solo está tratando de averiguar cómo enviar eventos del servidor al cliente (y html 5 es una opción), le recomiendo consultar server-sent events (o sockets web si necesita comunicación dúplex completa)Si html 5 no es una opción, creo que puede usar algunos hacks de javascript para simular sockets web. Puede leer sobre algunos de esos here y here.

de edición: añadido enlaces para que no sea HTML 5 alternativas

0

¿Es capaz de utilizar .NET 4.5 o está restringido a las versiones anteriores? v4.5 tiene muchas características nuevas que hacen que la creación de métodos asíncronos sea bastante directa sin tener que preocuparse por la administración de subprocesos. Este enlace tiene una buena explicación de cómo implementar un método asíncrono con la nueva tarea Task y async/await operadores: Working with Asynchronous Operations in ASP.NET 4.5 Web Forms

Esencialmente usted acaba de tener que crear una Task para cada método responsable de actualizar el UpdatePanel y dispararla en la carga de la página. Al finalizar cada tarea puede dormir durante 5 o 10 segundos antes de llamarse a sí mismo para darle el efecto que busca.

0

su lugar se puede utilizar 2 controles del temporizador, una con intervalo de 5000 y otra con el intervalo de 10.000

1

Sólo hay que poner una etiqueta de activación dentro de cada UpdatePanel que apuntan a un asp: Temporizador y establecer el intervalo de 5000 y 10000 milisegundos.

A continuación se muestra la solución que se le pregunte, utilizando UpdatePanel, pero tenga cuidado, porque cada uno de 5 y 10 segundos hay una PostBack despedido por temporizador:

Recomiendo el uso de javascript o jQuery para evitar las devoluciones de datos.

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!"; 
     } 
    } 
} 
Cuestiones relacionadas