ASP.Net: асинхронное обновление панели загрузки с двумя панелями обновления

8

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

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

Например:

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

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

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

Обе панели обновления настроены на updatemode="Conditional", и им предписано выполнять обратную передачу из клиентского javascript. Ниже приведен полный список приведенного выше примера.

Что мне здесь не хватает? Как получить одну панель обновления для загрузки, а затем другую, чтобы обе задачи выполнялись асинхронно?

Спасибо,

ТМ

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>

С #:

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();
    }
}
    
задан Owen Blacker 04.12.2009 в 17:28
источник

5 ответов

1

Просто поместите тег Trigger внутри каждой UpdatePanel, указывающий на таймер asp: и установите интервал в 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>

С #

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!";
        }
    }
}
    
ответ дан Stephan 14.08.2013 в 01:08
0

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

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

    
ответ дан Jim L 04.12.2009 в 17:44
0

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

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

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

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

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

    
ответ дан kmkemp 06.04.2012 в 20:08
0

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

    
ответ дан Sanjay 19.01.2013 в 13:50
0

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

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

    
ответ дан Nathon Fowlie 30.10.2012 в 06:39