ASP.Net:异步更新面板加载两个更新面板

时间:2009-12-04 16:28:11

标签: c# asp.net-ajax updatepanel

我正在尝试在数据检索任务需要不同时间的网站上的更新面板中异步显示数据。我想更新每个面板,以在每个任务完成后显示页面上的数据。

但是,无论我尝试什么,所有更新面板都会在上一个任务完成后更改其内容。

例如:

我有两个任务:

  • 尝试在5秒后更新 UpdatePanel1 中的标签的人
  • 尝试在10秒后更新 UpdatePanel2 中的标签的人

预期结果是在5秒后只有UpdatePanel1中的标签发生变化,但是,两个更新面板同时更新,时间为10秒。

两个更新面板都设置为updatemode =“Conditional”,并告诉他们从客户端javascript回发。以下是上述示例的完整列表。

我在这里缺少什么?如何让一个更新面板加载,然后另一个,让两个任务异步运行?

谢谢,

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

5 个答案:

答案 0 :(得分:1)

只需在每个UpdatePanel中放置一个指向asp:Timer的Trigger标记,并将间隔设置为5000和10000毫秒。

以下是您使用UpdatePanel提出的解决方案,但请注意,因为每次5秒和10秒都会为Timer启动PostBack:

我建议使用javascript或jQuery来避免PostBack。

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

答案 1 :(得分:0)

我怀疑你并不像你认为线程加入的b / c那样异步调用它。在线程2终止之前,看起来你基本上是在说块OnPrerender。 因为从同一个方法调用了1和2,所以在完成两个操作之前都会被阻塞。如果你投入一些书法来看看什么时候被调用,可能会更容易看到发生的事情。

我还怀疑在我所知道的预渲染完成之前,1上的文字不会真正更新。传统的ASP.NET,在 prerender完成之后 但是我对更新面板知之甚少,所以我可以在那个上面谈论垃圾,并期待被标记下来......

答案 2 :(得分:0)

预渲染处理程序中的连接阻止渲染返回到客户端。而不是你拥有的东西,我怀疑你可以做这样的事情:

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

然而,该代码具有依赖于知道哪个线程将首先返回的不幸副作用。

但是,如果您只是想弄清楚如何将事件从服务器发送到客户端(并且html 5是一个选项),我建议您查看server-sent events(或者如果您需要,请查看网络套接字)全双工通信)。如果html 5不是一个选项,我相信你可以使用一些javascript hacks来模拟web套接字。您可以阅读其中一些herehere

编辑:添加了非HTML 5替代品的链接

答案 3 :(得分:0)

您是否可以使用.NET 4.5或者您是否仅限于早期版本? v4.5有很多新功能,可以非常直接地创建异步方法,而不必担心线程管理。此链接很好地解释了如何使用新的Task任务和async / await运算符实现异步方法:Working with Asynchronous Operations in ASP.NET 4.5 Web Forms

基本上,您只需为每个负责更新updatepanel并在页面加载时启动它的方法创建Task。完成后,每个任务都可以睡5到10秒,然后再调用它来为你提供效果。

答案 4 :(得分:0)

相反,您可以使用2个定时器控件,一个间隔为5000,另一个间隔为10000