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);
}
}
}
I think there might be a few things going on here:
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();
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;
}
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With