ASP.Net: асинхронная загрузка панели обновления с двумя панелями обновления - PullRequest
8 голосов
/ 04 декабря 2009

Я пытаюсь асинхронно отображать данные в панелях обновления на веб-сайте, где задачи поиска данных занимают разное время. Я хотел бы обновить каждую панель, чтобы отображать данные на странице после завершения каждой задачи.

Однако, что бы я ни пытался сделать, все панели обновлений меняют свое содержимое после выполнения последней задачи.

Например:

У меня есть две задачи:

  • Тот, который пытается обновить метку в UpdatePanel1 через 5 секунд
  • Тот, который пытается обновить метку в UpdatePanel2 через 10 секунд

Ожидаемый результат - изменение только метки в UpdatePanel1 через 5 секунд, однако обе панели обновлений обновляются одновременно, через 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 ]

1 голос
/ 14 августа 2013

Просто поместите тег Trigger внутри каждой панели UpdatePanel, указывающий на таймер asp: Time, и установите интервал в 5000 и 10000 миллисекунд.

Ниже приведено решение, которое вы запрашиваете, используя UpdatePanel, но будьте осторожны, потому что каждые 5 и 10 секунд для таймера срабатывает PostBack:

Я рекомендую использовать javascript или jQuery, чтобы избежать 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!";
        }
    }
}
0 голосов
/ 19 января 2013

Вместо этого вы можете использовать 2 таймера, один с интервалом 5000, а другой с интервалом 10000

0 голосов
/ 06 апреля 2012

Объединения в вашем обработчике предварительного рендеринга блокируют рендеринг обратно клиенту. Я подозреваю, что вместо того, что у вас есть, вы могли бы сделать что-то вроде этого:

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

Этот код имеет неприятный побочный эффект, поскольку зависит от того, какой поток вернется первым.

Однако, если вы просто пытаетесь выяснить, как отправлять события с сервера на клиент (вариант html 5), я бы рекомендовал изучить события, отправленные на сервер (или веб-сокеты, если вам требуется полнодуплексная связь). Если HTML 5 не вариант, я думаю, вы можете использовать некоторые хаки Javascript для имитации веб-сокетов. Вы можете прочитать о некоторых из этих здесь и здесь .

edit: добавлены ссылки для не-HTML 5 альтернатив

0 голосов
/ 30 октября 2012

Можете ли вы использовать .NET 4.5 или вы ограничены более ранними версиями? В версии 4.5 есть много новых функций, которые делают создание асинхронных методов довольно простым, не беспокоясь об управлении потоками. Эта ссылка содержит хорошее объяснение того, как реализовать асинхронный метод с новой задачей Task и операторами async / await: Работа с асинхронными операциями в веб-формах ASP.NET 4.5

По сути, вам просто нужно создать Task для каждого метода, отвечающего за обновление панели обновления, и запустить его при загрузке страницы. По завершении каждая задача может спать в течение 5 или 10 секунд перед тем, как вызывать себя, чтобы получить желаемый эффект.

0 голосов
/ 04 декабря 2009

Я подозреваю, что вы не вызываете это так же асинхронно, как вы думаете, что б / с присоединяется к потоку. Похоже, вы в основном говорите block OnPrerender, пока поток 2 не завершится. Поскольку оба и 1 и 2 вызываются из одного и того же метода, вы заблокированы, пока оба не будут выполнены. Если вы добавите несколько писем, чтобы увидеть, когда что-то вызывается, вам может стать немного легче увидеть, что происходит.

Я также подозреваю, что текст на 1 не будет действительно обновляться, пока не будет завершен предварительный вывод из того, что я знаю. Традиционный ASP.NET, ничего не отправляется обратно клиенту до тех пор, пока после завершения prerender не завершится. Но я не очень разбираюсь в панели обновлений, так что я мог бы говорить об этом на макулатуре и предвкушать, что меня унизят ...

...