Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Progress Bar in c#

I'm looking for a way to display a "progress bar" in web using webforms with c#.

I made a quick example, I just want a label to show like 1%, 2%, 3% etc.. about a background process that will be running in the server. And when it finish update something like showing an alert or something, The real need is a little more complicated than that but getting the bases I think I can make it by my own. The problem that I having with the code is that I'm always getting 0.. in my "progress bar" it doesn't get updated, I'm missing something but I don't know what it is.

Edit

I tried to alert the value every second to see the value instead of the label, but it is not working anyway.

I missed the OnClientClick="javascript:GetProgress();" in the first queston, i Updated it, it is not working anyway

Edit 2

HttpConext.Current is being null when calling it as a thread.. Should I use something more than a session or application, perhaps a singletone class?

Any Help would be really appreciated.


Importanth thigs from The ASPX and JS

 <div style="width: 800px" class="css_container">
        <cc1:ToolkitScriptManager ID="sm" runat="server" EnableScriptGlobalization="true"
            EnableScriptLocalization="true" AsyncPostBackTimeout="60000" EnablePageMethods="true">
        </cc1:ToolkitScriptManager>
        <asp:UpdatePanel ID="upPanel" runat="server">
            <ContentTemplate>
               <asp:Button ID="btn" runat="server"  Text="Do Something"
                                    CausesValidation="False" OnClick="btn_Click" OnClientClick="javascript:GetProgress();" />
            </ContentTemplate>
        </asp:UpdatePanel>
  </div>

  function GetProgress() {
       PageMethods.GetProcessed(function(result) {
                alert(result);
                if (result < 100) {
                    setTimeout(function(){GetProgress();}, 1000);
                }                  
            });

    }

Important Things from Code Behind

[WebMethod(EnableSession=true), ScriptMethod]
    public  static string GetProcessed()
    {
        return HttpContext.Current.Session["processed"].ToString();
    }

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
             Session["processed"] = 0;
        }
    }

protected void btn_Click(object sender, EventArgs e)
    {
       AClass oClass = new AClass();
        Thread oThread = new Thread(delegate()
            {
                oClass.UpdateSession();
            });
           oThread.Start();
    }

Important Things from the Aclass

public class AClass
{ 
    public void UpdateSession()
    {
          for(int i = 0; i< 100; i++)
          {

            HttpContext.Current.Session["processed"] =  i;
            System.Threading.Thread.Sleep(1000);
          }
    }
}
like image 428
Hector Sanchez Avatar asked Mar 02 '26 07:03

Hector Sanchez


2 Answers

I think there might be a few things going on here:

  1. Your thread might be terminating at the end of the response. I think you can fix that by changing the way you define your thread:

    Thread oThread = new Thread(new ThreadStart(oClass.UpdateSession));
    oThread.IsBackground = true; // Set this
    oThread.Start();
    
  2. You're returning a string percent to your callback function, and then comparing it against a number. It's not really an issue, but for the sake of good programming, you should change your server-side GetProcessed() to return an actual integer:

    public static int GetProcessed()
    {
        int result = 0;
        int.TryParse(HttpContext.Current.Session["processed"].ToString()), out result);
        return result;
    }
    
  3. UpdatePanel requests initiate a full page lifecycle behind the scenes. Can you verify that this code isn't resetting your progress every tick of your GetProcessed() web method?

    if (!IsPostBack)
    {
         Session["processed"] = 0;
    }
    
like image 128
Cᴏʀʏ Avatar answered Mar 03 '26 21:03

Cᴏʀʏ


The issue is that you are calling in on a different Session than the one the value is being updated on. So, you have a couple of options.

First you could make that an Application variable if your application is only used by one user (very unlikely but I don't know anything about the app).

Second, you can use some sort of correlation key so that you can get the value from an Application variable that is keyed.

Make a change in the button click:

protected void btn_Click(object sender, EventArgs e) 
{
    // NEW CODE
    // set the hidden field value here with a correlation key
    var correlationKey = Guid.NewGuid().ToString();
    this.correlationKey.Value = correlationKey;

    AClass oClass = new AClass(); 
    Thread oThread = new Thread(delegate() 
        { 
            oClass.UpdateSession(correlationKey); 
        }); 
    oThread.Start(); 
}

Now modify the JavaScript like this:

function GetProgress() {
    PageMethods.GetProcessed(document.getElementById("correlationKey").value,
        function(result) {
            alert(result);
            if (result < 100) {
                setTimeout(function(){GetProgress();}, 1000);
            }   
        });   
}

Now modify the GetProcessed method like this:

[WebMethod(EnableSession=true), ScriptMethod]
public  static string GetProcessed(string correlationKey)
{
    var dictionary = Application["ProcessedQueue"] as Dictionary<string, int>;
    if (dictionary == null || !dictionary.ContainsKey(correlationKey)) { return "0"; }
    return dictionary[correlationKey].ToString();
}

Now modify the UpdateSession method like this:

public void UpdateSession(string correlationKey)
{
    var dictionary = Application["ProcessedQueue"] as Dictionary<string, int>;
    if (dictionary == null)
    {
        dictionary = new Dictionary<string, int>();
        Application["ProcessedQueue"] = dictionary;
    }

    if (!dictionary.ContainsKey(correlationKey)) { dictionary.Add(correlationKey, 0); }

    for (int i = 0; i< 100; i++)
    {
        dictionary[correlationKey] =  i;
        System.Threading.Thread.Sleep(1000);
    }
}

And now clean out the Page_Load.

like image 24
Mike Perrenoud Avatar answered Mar 03 '26 21:03

Mike Perrenoud



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!