【问题标题】:Updating Webpage from Within Thread从线程内更新网页
【发布时间】:2017-06-29 11:27:32
【问题描述】:

我有一个运行冗长过程的网页,除了在页面上显示进度之外,它都在工作。

我有以下进度条(Bootstrap):

<div class="col-md-8">
  <label for="product-feed-progress">Progress</label>
    <div class="progress">
     <div class="progress-bar" role="progressbar" runat="server" id="prgProdFeed" style="min-width: 0em; width: 0%;">
                                    0%
     </div>
  </div>
</div>

在线程期间,我有以下调整 prgProdFeed 的宽度属性的 sn-p:

prgProdFeed.Attributes.Add("style", "width:" & ((p_objFeedInfo.Progress / p_objFeedInfo.Total) * 100).ToString() + "%")

我也试过了:

prgProdFeed.Style.Item("width") = ((p_objFeedInfo.Progress / p_objFeedInfo.Total) * 100).ToString() + "%"

它们都更改了当前位于更新面板中的栏的宽度属性(在计时器的滴答声上更新)。

为什么我的进度条没有在页面上更新?我可以使用检查器看到更新面板正在刷新,并且在调试器中显示宽度是正确的 - 视觉上没有任何变化。

任何帮助将不胜感激。

【问题讨论】:

  • 假设您有上千个并发用户打开您的页面。您是否对它们都有一个“长期运行”线程,或者每个线程都有一个?那么,您的长期运行线程(或多个线程)如何理解这千个用户中的哪一个每次都带有 UpdatePanel 请求?换句话说,如何将长时间运行的线程与特定的 http 请求同步?
  • 嗯,好吧,我明白你的意思了。我将继续寻找其他方式向用户展示进度。
  • @MrDKOz 您可以考虑使用 SignalR 或网络套接字。
  • Lanorkin Asp.Net 是为处理这些情况而构建的。这不是问题。然而,正如@NKosi 所建议的那样,对于这样的事情,有更有效的方法。即使创建一个通用处理程序来获取作为 JSON 对象的进度也比使用更新面板要好得多。一般来说,更新面板在工作时很棒,但它不会让你扯掉你的头发。我在下面发布了一个带有工作代码的答案。

标签: asp.net vb.net multithreading twitter-bootstrap


【解决方案1】:

工作代码如下。

我建议您确保您的更新面板实际上正在刷新。使用我的代码,您可以对网页进行硬更新(例如 F5),您会看到更新的进度。最初,我刷新更新面板的代码没有触发。我使用 Query 触发点击更新面板中的刷新链接按钮,但我需要更改代码以调用 __doPostBack。

我要检查您的代码的另一件事是 p_objFeedInfo.Progress 是双精度,p_objFeedInfo.Total 是双精度。您可能会遇到一个问题,其中一个是 int,并且 (p_objFeedInfo.Progress / p_objFeedInfo.Total) 小于 1 的双精度结果被转换为整数,在乘以 100 之前向下舍入为 0。

此外,我将 width 属性组合成一个字符串,并将 prgProdFeed.InnerText 设置为该字符串,因此我无需担心检查元素以查看宽度是否在变化。我也在设置宽度使用 Style("Width"):

Dim progressAttribute As String = progress & "%"
Me.prgProdFeed.Style("Width") = progressAttribute
Me.prgProdFeed.InnerText = progressAttribute

为了模拟您长时间运行的线程,我创建了一个以Total 作为构造函数的提要类。它根据自创建类以来经过的秒数返回双倍进度。

Public Class ProgressBar
    Inherits System.Web.UI.Page

    Public Class FeedInfo
        Public ReadOnly Property Progress As Double
            Get
                Return Math.Min(Now.Subtract(Created).TotalSeconds, Total)
            End Get
        End Property

        Public Total As Double
        Public Created As DateTime
        Public Sub New(Total)
            Me.Total = Total
            Created = Now
        End Sub
    End Class
    Private Property info As FeedInfo
        Get
            If (Not Session("info") Is Nothing) Then
                Return Session("info")
            End If
            Return Nothing
        End Get
        Set(value As FeedInfo)
            Session("info") = value
        End Set
    End Property

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim progress As Integer = 0
        If (Not info Is Nothing) Then
            Dim tracker As FeedInfo = info
            Dim trackerProgress As Double = tracker.Progress
            Dim trackerTotal As Double = tracker.Total
            progress = ((trackerProgress / trackerTotal) * 100)
        End If
        Dim progressAttribute As String = progress & "%"
        Me.prgProdFeed.Style("Width") = progressAttribute
        Me.prgProdFeed.InnerText = progressAttribute

    End Sub

    Private Sub runProc_Click(sender As Object, e As EventArgs) Handles runProc.Click
        info = New FeedInfo(600)
    End Sub
End Class
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="ProgressBar.aspx.vb" Inherits="EFWCFVB.ProgressBar" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Long Running Task Progress Bar</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script>
        var timerId = 0;
        function trackProgress() {
            if (timerId && timerId != 0)
                return;
            timerId = window.setInterval(refreshProgress, 2000);
        }
        function refreshProgress() {
            if ($('.progress-bar').html() == "100%") {
                window.clearInterval(timerId); return;
            }
            //  $('#btnRefresh').click(); does not work
            // var href = $('#btnRefresh').attr("href").split[0]; //"javascript:__doPostBack('btnRefresh','')"
            __doPostBack('btnRefresh', '');

        }
        $(document).ready(function () {
            trackProgress();
            $('#runProc').click(function () { trackProgress();})
        })
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <h2>Long Running Task Progress Bar</h2>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <div class="form-group">
                    <div class="col-md-8">

                        <label for="product-feed-progress">Progress</label>
                        <div class="progress">
                            <div class="progress-bar" role="progressbar" runat="server" id="prgProdFeed" style="min-width: 0em; width: 0%;">
                                0%
                            </div>
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-8">
                        <asp:Button ID="runProc" runat="server" Text="Run" />
                        <asp:LinkButton ID="btnRefresh" runat="server" Text="Refresh Panel">

                        </asp:LinkButton>
                    </div>
                </div>
            </ContentTemplate>

        </asp:UpdatePanel>


    </form>
</body>
</html>

【讨论】:

    【解决方案2】:

    “宽度”不是条形图对象的正确属性。通常,width 表示整个对象的宽度。

    您需要寻找“value”属性而不是“width”

    【讨论】:

    • 我做到了:我告诉了“价值”。但无论如何感谢您的反对。
    • 您是否尝试过寻找“值”而不是“宽度”?。不要假设谁是 dv,而是尝试改进您的答案
    • 请确保一旦我有权发表评论,我就会发表评论而不是试图建议要考虑的事情。不过,我认为我的回答可能会有所帮助。
    猜你喜欢
    • 2018-03-09
    • 1970-01-01
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    相关资源
    最近更新 更多