Is the update panel incompatible with "Page async = true"? RRS feed

  • Question

  • User-1112034352 posted

    I made a page that uses a class that uploads a file to azure.  The class that does this takes a few  minutes to upload and then encode the file, so I want the page to periodically tell the user how much progress is being made.  I thought of using a progress bar, but I think I''m better off with messages that would appear in a label, such as "Created asset" or "Starting to encode".  

    I was given one method (not using the ajax control kit but definitely using ajax), which I have not tried out yet.  However, I then thought of using a timer with an update panel.  I would just create an update panel, with  [UpdateMode="Always"], and put the label and a timer in the update panel.  

    The timer would fire every few seconds, and then the update panel would refresh, and the actual timer event (Timer1_Tick) would set the contents of the label inside the update panel.  (The timer would set the contents of the label to a session variable that is filled by the task periodically.  So if the task updates an event in my page with a message like "encoded 50%", I would store that message in a session variable.  Then, when the timer event itself fires, it can look at what is stored in the session variable, and update a label with it.

    But I ran into a big problem.  My code-behind page uses a "backgroundworker", which demands that the Page be declared as "Async".  I find that when I do that, the timer event simply does not fire.

    I think the reason (vaguely) is that the async attribute prevents the page from staying as one thread.  So when the timer fires, its not finding the thread that it expects.

    Here are fragments of  my code and html.  Its fairly simple

    <%@ Page Title="" Language="VB" Async="true" etc. %>
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
               <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always" >
                  <asp:TextBox ID="TextBoxLog" runat="server" TextMode="MultiLine" Rows="5"  Width="550px" ReadOnly="true"
    Visible="false" BackColor="sandybrown"></asp:TextBox>
                      <asp:Timer ID="Timer1" runat="server" Interval="1000" Enabled="false"></asp:Timer><br />
                      <asp:Label ID="Labelerror2" SkinID="errorlabel" runat="server"  />
                <asp:Label ID="Label1" runat="server" Text="Please enter the entire path of the video (on your PC) to upload to Azure" 
               <tr><td style="text-align:center">
                   <asp:TextBox ID="TextBoxFileName" runat="server" Width="273px"></asp:TextBox>
               <tr><td style="text-align:center">
                   <asp:Button ID="ButtonSubmit" runat="server" Text="Submit" />
            <asp:Label ID="LabelError" SkinID="errorlabel" runat="server" EnableViewState="false" ClientIDMode="Static" />

    above was the html, now here is the code:

    Imports System.ComponentModel
    Partial Class zOwner_UploadAzure
        Inherits System.Web.UI.Page
        Protected Sub ButtonSubmit_Click(sender As Object, e As EventArgs) Handles ButtonSubmit.Click
            Dim strName As String
            strName = Me.TextBoxFileName.Text.Trim
            If Not ClassStrings.IsValidFileName(strName, True) Then
                Me.LabelError.Text = "Error, the filename you supplied does not fit the Windows format of filenames."
                Exit Sub
            End If
            Me.TextBoxLog.Visible = True
     ' Azurex is my class that does time consuming operations, no need to view it here
            AzureNameSpaceGid.Azurex.userpcfilename = strName
            Dim worker As BackgroundWorker = New BackgroundWorker()
            worker.WorkerReportsProgress = True
            AddHandler worker.DoWork, AddressOf AzureNameSpaceGid.Azurex.UploadFile
            AddHandler worker.ProgressChanged, New ProgressChangedEventHandler(AddressOf worker_ProgressChanged)
            Me.Labelerror2.Text = "Starting..."
            Me.Timer1.Enabled = True
            Session("hitsubmit") = True
        End Sub
        Private Sub worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
            Dim obj As Object
            obj = e.UserState
            Dim strMessage As String
            strMessage = obj.ToString
           If strMessage.StartsWith("LOGMESSAGE_") Then
                Session("strerror") = Session("strerror") & vbCrLf & "<br />" & strMessage.Substring(11)
                Session("strprogress") = Session("strprogress") & vbCrLf & strMessage
            End If
        End Sub
        Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
            If Not Page.IsPostBack Then
                Session("hitsubmit") = False
                Session("strprogress") = ""
                Session("strerror") = ""
            End If
            If Session("hitsubmit") Then
                Me.Timer1.Enabled = True
            End If
        End Sub
        Protected Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            Me.TextBoxLog.Text = Session("strprogress")
            Me.Labelerror2.Text = Session("strError")
        End Sub
    End Class

    I am 80 percent sure that the Page Async attribute somehow interferes with Ajax, because when I tested the code without it (I also had to remove the backgroundworker in this case, the timer does fire, the update panel contents to get set to visible, etc.


    P.S. I just noticed a missing line in Page_Load: it should have   Me.TextBoxLog.Visible = True --- under the statement that enables the timer.  But this doesn't change anything - the timer does not fire.

    Monday, November 4, 2013 7:25 AM


All replies

  • User-1112034352 posted

    I looked at the references you gave, and the first isn't a link, the third doesn't talk about ajax, and the second does, but it doesn't seem to solve the problem.  It really is odd.  I found out that the problem is not that the Page is 'async', which I had thought originally.  The problem arises if the background worker fires a 'progress-event' in the page.  When that happens, then the timer in the page itself can no longer find the page.  Or at least it gets unhooked from the timer event, or turned off, or whatever.

    To make clear what I did, it was the following:

    1. the background worker manages a class with a lengthy operation in it that reports progress periodically.

    2. this progress report fires an event in the webpage code-behind telling the page how much progress has been made.  I store that progress in a session variable

    3. I add a timer control to the page.  It fires an event in the code-behind.  That event reads the session variable and sets a label in the main page.  Both the label in question, and the timer, are in an update panel.  Note that without the background worker sending progress reports, this DOES work.  But as soon as the background worker sends a progress report (by firing its event), the timer no longer finds its event.   Maybe this has to do with threading in some way.  

    (The reason I use an update panel is that I don't want to update the entire page, just that one label in it, with progress reports).

    If this worked, it would provide an easy way to combine backgroundworker, which is a simple way of doing async big operations, with the timer/update-panel mechanism, which is a simple way of reporting progress (all the ajax is invisible to the programmer).  But it is not working.

    (The routine called is:

    Private Sub worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)




    Wednesday, November 6, 2013 7:34 AM
  • User555306248 posted

    The UpdatePanel call to the server is not really asynchronous, it just hides the postback from the user but the page still goes through the whole life cycle, on the other hand calls to WebServices and PageMethods are made asynchonously.




    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, November 6, 2013 11:16 PM