I am trying to asynchronously display data in update panels on a website where the data retrieval tasks take different times. I would like to update each panel to show the data on the page after each task finishes.
However, no matter what I try, all Update Panels change their content after the last task has completed.
For example:
I have two tasks:
The expected result is to have only the label in UpdatePanel1 change after 5 seconds, however, both update panels update at the same time, at 10 seconds.
Both update panels are set to updatemode="Conditional" and they are told to postback from client javascript. Below is a complete listing of the example above.
What am I missing here? How do I get one update panel to load, and then the other, having both tasks run asynchronously?
Thanks,
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();
}
}
Just put a Trigger tag inside each UpdatePanel pointing to a asp:Timer and set interval to 5000 and 10000 miliseconds.
Below is the solution that you ask, using UpdatePanel, but take care because each 5 and 10 seconds there is a PostBack fired for Timer:
I recommend using of javascript or jQuery to avoid 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!";
}
}
}