|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
Can you give an example of how I would update the progressbar from the server side during a LONG running process?
Code: C#
ProgressBar1.Maximum = ProcessQueue.Count;
ProgressBar1.Value = 0;
foreach (Process in ProcessQueue)
{
if (Process.DoSomething())
UpdateProgressBarHere();
}
private void UpdateProgressBarHere()
{
// Here's where i need some help!
ProgressBar1.Value++;
}
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, ProgressBar is designed to be updated on the client side, not on the server side: http://www.essentialobjects.com/ViewDoc.aspx?t=JSDoc.Public.ProgressBar.setValue.htmlIf you do need the ProgressBar to be updated on the server side, you can use a Callback control to call server side code to return the current progress value, then call the above function to set the value. Thanks
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
Can you give a quick code example of how this would work. I know nothing about javascript, and less about callbacks.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, It would be rather hard to explain to you if you are not familar with Javascript. :) So I'll try to break it into a couple of steps. The first step is to know how to update the progress bar. We have two samples demonstrating how to do that at here: http://www.essentialobjects.com/Demo/Default.aspx?path=ProgressBarOnce you are familar with that, you want to play with the Callback control a bit. You can start by looking at the samples in the demo projects, but then you will need to play with this function: http://www.essentialobjects.com/ViewDoc.aspx?t=JSDoc.Public.Global.eo_Callback.htmlOnce you learned how this function work, you would need to proceed to these two things: 1. Use window.setTimeout or whatever other mechanism to call eo_Callback; 2. Handle this event to update progress bar; http://www.essentialobjects.com/ViewDoc.aspx?t=EO.Web.Callback.ClientSideAfterExecute.htmlSo the whole flow is like timer (window.setTimeout) -> eo_Callback -> ClientSideAfterExecute -> ProgressBar.setValue. This will be running repeatly until the task is done. We maybe able to add a demo into the demo project when we release our next update. Thanks
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
I think I understand what we're are doing, but I'm not doing something right. Can you give a quick working example? I have the progressbar on a control that I need to update say every 5 seconds. I have a callback on the control as well. Server Side:
Code: C#
public void SendNOW(NewsLetterEntity N)
{
Page.RegisterStartupScript("PBShow", "javascript: setTimeout('executeCallback()',5000)");
ProgressBar1.Maximum = SubscriberCollection.ActiveSubscribers.Count;
ProgressBar1.Value=0;
foreach (SubscriberEntity S in SubscriberCollection.ActiveSubscribers)
{
WebMail.SendNewsletter(N, S);
ProgressBar1.Value++;
}
}
protected void Callback1_Execute(object sender, EO.Web.CallbackEventArgs e)
{
e.Data = ProgressBar1.Value.ToString();
}
On the client side: I have the following code
Code: JavaScript
function executeCallback() {
eo_Callback('callback1');
}
function updateProgressBar(var Callback, var Output, var Value) {
eo_GetObject('ProgressBar1').setValue(Value);
}
I'm not sure how to set the Timer code as I am in a control, and not sure how to access the Body onload event. Any help would be greatly appreciated.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, You don't need to do Page.RegisterStartupScript. The easiest way is to do:
Code: HTML/ASPX
<body onload="setTimeout('executeCallback()',5000)">
Also, setTimeout only triggers once, so in order for it to trigger repeatly, you would want to do:
Code: JavaScript
function executeCallback()
{
eo_Callback('callback1');
setTimeout('executeCallback()',5000);
}
The rest of your code looks good. Thanks
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
The problem I have now is accessing the <body onload> from the code in the component. This control doesn't have the <body> tag as it is in the MasterPage.
How can I either 1) update the body tag on the masterpage from a control? or 2) start the process from my control.
Thanks
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi,
In that case you will need to use RegisterStartupScript. The only catch with this function is you need to enclose your code in the script tag. For example this is wrong:
Page.RegisterStartupScript("window.alert('hi!')");
This is correct:
Page.RegisterStartupScript("<script language='javascript'>window.alert('hi!')</script>");
Thanks
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
You know I'm still having a problem :( I move this code out of a control and put it directly on the page. I still cannot get this thing working. Plus, the ProgressBar control seems to have a display bug in it. I'll try to attach some screen captures. First, Here's my code:
Code: HTML/ASPX
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="88836f54-1540-4760-a9c1-a9b7e105edad.aspx.cs"
Inherits="_88836f54_1540_4760_a9c1_a9b7e105edad" %>
<%@ Register Assembly="EO.Web" Namespace="EO.Web" TagPrefix="eo" %>
<!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>
<script type="text/javascript">
function executeCallback() {
window.alert(eo_GetObject('ProgressBar1').getValue());
eo_Callback('Callback1');
setTimeout('executeCallback()',5000);
}
function updateProgressBar(var Callback, var Output, var PBValue) {
eo_GetObject('ProgressBar1').setValue(PBValue);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<eo:Callback ID="Callback1" runat="server" OnExecute="Callback1_Execute" ClientSideAfterExecute="updateProgressBar">
</eo:Callback>
<table style="width: 100%">
<tr>
<td align="center" class="TextHeader">
Sending Newsletters</td>
</tr>
<tr>
<td align="center">
<eo:ProgressBar ID="ProgressBar1" runat="server" BorderColor="Black" BorderStyle="Solid"
BorderWidth="1px" ControlSkinID="None" Height="16px" IndicatorColor="0, 192, 0"
Value="30" Width="500px">
</eo:ProgressBar>
</td>
</tr>
<tr>
<td align="center">
<VAM:Button ID="ButtonGO" runat="server" OnClick="ButtonGO_Click" OnClientClick="eo_Callback('Callback1')"
Text="GO" Width="100px" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Code: C#
public partial class _88836f54_1540_4760_a9c1_a9b7e105edad : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ButtonGO_Click(object sender, EventArgs e)
{
int X = 100;
ProgressBar1.Maximum = X;
ProgressBar1.Value = 0;
for (int i = 0; i < X; i++)
{
ProgressBar1.Value++;
System.Threading.Thread.Sleep(500);
}
}
protected void Callback1_Execute(object sender, EO.Web.CallbackEventArgs e)
{
e.Data = ProgressBar1.Value.ToString();
}
}
Here are my screen captures:
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi,
Somehow the screenshot is not working. However I spotted at least one error in your code: you can not perform task like what you did in ButtonGO_Click. ASP.NET threading modal prevent you from having two requests from the same user to be executed at the same (ever wondering why you never need to worry about threading issues in an ASP.NET application?). So in your case when your ButtonGO_Click is being executed, the subsequent Callback requests will all be queued up by ASP.NET until ButtonGO_Click is done.
You will have to modify your code to make ButtonGO_Click to initiate the task and return immediately. Only after that ASP.NET will pick up subsequent Callback requests.
Thanks
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
Ok, so there's no way to push a javascript update to the client WHILE this long process is running?
U know I ran across some ProgressBar code that did allow to issue an update via javascript while a long process was running, and the client would update it's value. Once the process was all done, in the source code you could see every update that was sent. (I only wish I could find it)
Also, I've updated my screen capture of the progress bar. It displays this was in the IDE as well.
Your thoughts?
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi,
Try to remove align="center" on the enclosing td. Center alignment doesn't work on quite somethings and unfortunately progress bar is one of them.
Thanks
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, As for the long running process, I believe what you concluded is false. The problem is your code is blocking current request. The client side javascript is unable to get any status information not because the client side code is unable to query the server, but because your server code is never able to respond until your long running task is done. It has nothing to do with the progress bar or whatever client solution you might use. Try think your server code as "one man", it can not perform the long running task and also response status inquiry at the same time unless you explicitly make it multi-threaded. As such I do believe the only solution is to change your server side code structure. Thanks Vagyok C4 wrote:Ok, so there's no way to push a javascript update to the client WHILE this long process is running?
U know I ran across some ProgressBar code that did allow to issue an update via javascript while a long process was running, and the client would update it's value. Once the process was all done, in the source code you could see every update that was sent. (I only wish I could find it)
Also, I've updated my screen capture of the progress bar. It displays this was in the IDE as well.
Your thoughts?
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
I understand the threading issues with regards to the client PULLing data from the server while it's busy.
What I'm talking about is the server PUSHing the update to the client while this long running process is going.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
I see what you meant. However a web server never pushes. One of the biggest reason why HTTP is so popular is because of its request-response model.
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
We can do a Response.Write("<script>SetVallue(10);</script>"); Resposne.Flush(); which would "push" the updated value over to the client.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
No. That will not work. Response.Write only works when there is a request that it is responding to. HTTP works on a request-response basis and whatever you do with Response is only responding a request initiated by the client.
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
Ah ha! I found my old Progress Bar Code... The BLOG Document describing this functionality can be found at this link: Progress Bar Blog EntryYour thoughts?
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Thanks for sharing, the idea is rather clever. However it has to use a separate page with only the progressbar, I guess if you can live with that then you can go with it.
|
|
Rank: Member Groups: Member
Joined: 7/28/2007 Posts: 21
|
Is it possible to have your control make it easy to implement something like this? Giving the ability to progress bar out a long running process this way is a feature I think a lot of people would be interested in.
|
|