Hey Luca,Sorry for the long time to reply. Was out of town and just got back to work this morning.
It looks like your "Test_Click" function is syncronous, not asyncronous. In other words, when you call this.test_click() from StartProcessing_Callback(), it copies the file 10 times and then returns to StartProcessing_Callback(). Then it returns to your WCSX page. So before you ever check on the progress (by your page script calling the UpdateProgress_Callback() function on the page), the work you are checking for progress on is already done.
What you need is to set up a seperate asyncronous process to copy the files, and as it works have it update a variable or property with it's progress. Then in your Test_Page.prg file have your UpdateProgress_Callback() function check the var or property holding the percentage of progress and return that value to the Ajax call.
You can see a sample of an asyncronous process like you need at Asyncronous Server Calls under the Enterprise Features on the demo site.
Marty
Hi Marty,
the code is all in the same file Test_page.prg.
I attach the full prg code to avoid mistakes:
#INCLUDE WCONNECT.H
PRIVATE __WEBPAGE
__WEBPAGE = CREATEOBJECT("test_Page_WCSX")
__WEBPAGE.Run()
RELEASE __WEBPAGE
RETURN
DEFINE CLASS test_Page as WWC_WEBPAGE OF WWC_WEBPAGE_FILE
*** Your Implementation Page Class - put your code here
*** This class acts as base class to the generated page below
*****************************************************************
#IF .F.
LOCAL this as test_Page_WCSX of test_page.prg
#ENDIF
EnableSessionState = .T.
* OnLoad
****************************************
FUNCTION OnLoad()
ENDFUNC
*******************
FUNCTION Menu_click
IF Server.cMenu="MenuBo"
Response.Redirect("MenuBo.wc")
ELSE
Response.Redirect("MenuRe.wc")
ENDIF
ENDFUNC
FUNCTION test_click
#IF .F.
LOCAL this as test_Page_WCSX of test_page.prg
#ENDIF
FOR m.counter=1 TO 10
Session.SetSessionVar("simulate_Counter",TRANSFORM(m.Counter))
ERASE d:\bo.dbf
COPY FILE c:\temp\bo.dbf to d:\bo.dbf
endfor
ENDFUNC
* progressbar_Page :: StartProcessing
****************************************
*** Function: Callback method that starts off the request processing
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION StartProcessing_Callback()
Session.SetSessionVar("Simulate_Counter","0")
*** generate an ID to pass back to the client so
*** the client and server have context
lcId = SYS(2015)
Session.SetSessionVar("progress_Id",lcId)
Session.SetSessionVar("progress_StartTime",TRANSFORM(SECONDS()))
this.test_click
RETURN lcId
ENDFUNC
* progressbar_Page :: UpdateProgress
****************************************
*** Function: Callback method pinged by the client to see if the
*** request is done or cancelled.
*** Assume: ProgressEventArgs is defined in WebControlsExtended
*** Pass:
*** Return:
************************************************************************
FUNCTION UpdateProgress_Callback(llCancel)
lnCounter = VAL( Session.GetSessionVar("simulate_Counter") )
LOCAL loArgs as ProgressEventArgs
loArgs = CREATEOBJECT("ProgressEventArgs")
*** so we have to parse 'true'
IF llCancel
loArgs.Cancelled = .t.
loArgs.Percent = lnCounter
RETURN loArgs
ENDIF
IF lnCounter >= 100
loArgs.Completed = .T.
loArgs.Percent = 100
RETURN loArgs
ENDIF
*** OPERATIONS. FOR EXAMPLE, YOU COULD USE wwWebAsyncRequest
*** TO OFFLOAD PROCESSING TO ANOTHER PROCESS AND CHECK FOR
*** COMPLETION ON THE EXTERNAL PROCESS
*** In this sample - we just increment a counter
*lnCounter= lnCounter + 20
*lnCounter=lnCounter+1
*WAIT WINDOW NOWAIT TRANSFORM(lncounter) TIMEOUT 1
loArgs.Percent = lnCounter
RETURN loArgs
* progressbar_Page :: ProcessCompleted
****************************************
*** Function: Callback from the client called when the request is
*** complete (100% reached). Calls back to this method
*** and returns a DataGrid as HTML, which is merged into
*** client document.
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION ProcessComplete_Callback()
SELECT Company,Careof,Phone FROM TT_CUST INTO CURSOR TQuery
LOCAL loDg as wwWebDataGrid
loDg = CREATEOBJECT("wwWebDataGrid")
loDg.AUTOGENERATECOLUMNS = .t.
loDg.CssClass = "blackborder"
loDg.DataSource = "TQuery"
loDg.DataBind()
lcOutput = loDg.Render()
RETURN lcOutput
ENDFUNC
ENDDEFINE
*******************************************************
*** Generated by WebPageParser.prg
*** on: 04/19/2012 05:00:50 PM
***
*** Do not modify manually - class will be overwritten
*******************************************************
DEFINE CLASS test_Page_WCSX AS test_Page
Id = [test_Page]
HIDDEN CTL0002
CTL0002 = null
Header = null
HIDDEN CTL0004
CTL0004 = null
HIDDEN CTL0005
CTL0005 = null
form1 = null
HIDDEN CTL0007
CTL0007 = null
HIDDEN CTL0008
CTL0008 = null
HIDDEN CTL0009
CTL0009 = null
Progress = null
HIDDEN CTL0011
CTL0011 = null
ShowCode0 = null
HIDDEN CTL0013
CTL0013 = null
ShowCode1 = null
HIDDEN CTL0015
CTL0015 = null
HIDDEN CTL0016
CTL0016 = null
HIDDEN CTL0017
CTL0017 = null
FUNCTION Initialize(loPage)
LOCAL __lcHtml
DODEFAULT(loPage)
THIS.Attributes.Add("Language","C#")
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[<!DOCTYPE html>]+ CRLF +;
[<html>]
THIS.CTL0002 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0002")
THIS.CTL0002.Text = __lcHtml
THIS.AddControl(THIS.CTL0002)
THIS.Header = CREATEOBJECT("wwwebhead",THIS.Page,"Header")
THIS.AddControl(THIS.Header)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[ <title>Progress Bar and AJAX Demo</title>]+ CRLF +;
[ <link href="westwind.css" rel="stylesheet" type="text/css" />]
THIS.CTL0004 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0004")
THIS.CTL0004.Text = __lcHtml
THIS.CTL0004.UniqueId = [Header_CTL0004]
THIS.Header.AddControl(THIS.CTL0004)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[<body>]+ CRLF +;
[ ]
THIS.CTL0005 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0005")
THIS.CTL0005.Text = __lcHtml
THIS.AddControl(THIS.CTL0005)
THIS.form1 = CREATEOBJECT("wwWebform",THIS.Page,"form1")
THIS.AddControl(THIS.form1)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[ <h1>Progress Bar</h1>]+ CRLF +;
[ ]+ CRLF +;
[ <div class="toolbarcontainer">]+ CRLF +;
[ <a href="default.htm" class="hoverbutton"><img src="../images/home.gif" /> Sample Home</a> | ]+ CRLF +;
[ <a href="progressBar.wcsx" class="hoverbutton"><img src="../images/refresh.gif" /> Reset Form</a> | ]+ CRLF +;
[ <small>Rendered at: ]
THIS.CTL0007 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0007")
THIS.CTL0007.Text = __lcHtml
THIS.AddControl(THIS.CTL0007)
THIS.CTL0008 = CREATEOBJECT("EvalControl",THIS.Page,"CTL0008")
THIS.CTL0008.EvalExpression = [ DateTime() ]
THIS.AddControl(THIS.CTL0008)
__lcHtml = []
__lcHtml = __lcHtml + [</small>]+ CRLF +;
[ </div>]+ CRLF +;
[ ]+ CRLF +;
[ <div class="descriptionheader" >]+ CRLF +;
[ This sample demonstrates how to asynchronously run a task on the server while displaying]+ CRLF +;
[ progress in the current page by utilizing AJAX. Using this mechanism it's possible to run long running]+ CRLF +;
[ tasks in the background and continue working on the client side while displaying context ]+ CRLF +;
[ specific progress.]+ CRLF +;
[ </div>]+ CRLF +;
[ ] + CRLF
__lcHtml = __lcHtml + [ <div class="containercontent" style="margin: 0 auto;text-align: left;">]+ CRLF +;
[ ]+ CRLF +;
[ <input id="btnStartProcessing" type="button" value="Start Processing" onclick="StartProcessing()" />]+ CRLF +;
[ <input id="btnStopProcessing" type="button" value="Cancel Processing" onclick="Cancelled = true;" />]+ CRLF +;
[]+ CRLF +;
[]+ CRLF +;
[ <div style="margin: 20px;">]+ CRLF +;
[ ]
THIS.CTL0009 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0009")
THIS.CTL0009.Text = __lcHtml
THIS.AddControl(THIS.CTL0009)
THIS.Progress = CREATEOBJECT("wwwebprogressbar",THIS.Page,"Progress")
THIS.Progress.Text = [Waiting to get started]
THIS.Progress.Width = [500px]
THIS.AddControl(THIS.Progress)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[ </div>]+ CRLF +;
[ ]+ CRLF +;
[ <!-- Demonstrate manually updating the progress bar -->]+ CRLF +;
[ <input type="text" id="txtPercent" value="58" size="4"/>]+ CRLF +;
[ <input id=btnSetPercent" type="button" value="Set Percentage" ]+ CRLF +;
[ onclick="UpdateProgressBar('Progress',$('#txtPercent').val(),'Updated...')" /> ]+ CRLF +;
[ <hr /> ]+ CRLF +;
[ ]+ CRLF +;
[ <div id="lblResult"></div> ] + CRLF
__lcHtml = __lcHtml + [ ]+ CRLF +;
[ <blockquote>]+ CRLF +;
[ This example demonstrates using the wwWebProgressBar control to show progress of an operation running on the server.]+ CRLF +;
[ The server form has three client functions: StartProcessing, UpdateProgress and ProcessComplete, which are fired from script]+ CRLF +;
[ code using the wwMethodCallbackControl that handles the remote processing.]+ CRLF +;
[ <br />]+ CRLF +;
[ <br />]+ CRLF +;
[ The code pings this server once a second and requests updated status information - an object returned from the server]+ CRLF +;
[ that contains a message a percentage and completion and cancellation status in this case. If complete the client calls]+ CRLF +;
[ the server again to ProcessComplete which returns a final result in the form of a DataGrid generated string to the] + CRLF
__lcHtml = __lcHtml + [ client. ]+ CRLF +;
[ <br />]+ CRLF +;
[ <br />]+ CRLF +;
[ All of this happens in the context of a single page, without post backs. Notice that during the update process the]+ CRLF +;
[ page remains live so you can for example set the percentage manually with the percentage button. The value will be]+ CRLF +;
[ set briefly until the next server update brings back more information and updates the progress bar again.]+ CRLF +;
[ </blockquote>]+ CRLF +;
[ ]+ CRLF +;
[ <hr />]+ CRLF +;
[ ] + CRLF
__lcHtml = __lcHtml + [ ]
THIS.CTL0011 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0011")
THIS.CTL0011.Text = __lcHtml
THIS.AddControl(THIS.CTL0011)
THIS.ShowCode0 = CREATEOBJECT("wwwebshowcode",THIS.Page,"ShowCode0")
THIS.ShowCode0.DisplayMode = [WCSX]
THIS.ShowCode0.Text = [Show WCSX]
THIS.AddControl(THIS.ShowCode0)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[ ]
THIS.CTL0013 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0013")
THIS.CTL0013.Text = __lcHtml
THIS.AddControl(THIS.CTL0013)
THIS.ShowCode1 = CREATEOBJECT("wwwebshowcode",THIS.Page,"ShowCode1")
THIS.ShowCode1.DisplayMode = [VFP]
THIS.ShowCode1.Text = [Show PRG]
THIS.AddControl(THIS.ShowCode1)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[ ]+ CRLF +;
[ </div>]+ CRLF +;
[ ]+ CRLF +;
[<script type="text/javascript">]+ CRLF +;
[var Cancelled = false;]+ CRLF +;
[var TimerInterval = 500;]+ CRLF +;
[]+ CRLF +;
[function StartProcessing()]+ CRLF +;
[{] + CRLF
__lcHtml = __lcHtml + [ Cancelled = false;]+ CRLF +;
[ $('#btnStartProcessing').attr("disabled",true);]+ CRLF +;
[ $('#btnStopProcessing').attr("disabled",false); ]+ CRLF +;
[ $('#lblResult').html("");]+ CRLF +;
[ ]+ CRLF +;
[ // *** Progress_Ajax is the name of the Progress Control _Ajax for the wwWebAjax instance]+ CRLF +;
[ Progress_Ajax.callMethod("StartProcessing_Callback",[] + ']' + [,]+ CRLF +;
[ function(result) {]+ CRLF +;
[ // *** Start the chain - request progress information in timeout seconds]+ CRLF +;
[ window.setTimeout(GetProgress,TimerInterval); ] + CRLF
__lcHtml = __lcHtml + [ });]+ CRLF +;
[} ]+ CRLF +;
[function GetProgress()]+ CRLF +;
[{]+ CRLF +;
[ // *** Iniate a callback to the server to get the progress]+ CRLF +;
[ // *** Pass cancelled flag as parameter so server can now if to cancel]+ CRLF +;
[ Progress_Ajax.callMethod("UpdateProgress_Callback", [Cancelled] + ']' + [,]+ CRLF +;
[ // this returns the server's response as an object]+ CRLF +;
[ // result is ProgressEventArgs returned from server]+ CRLF +;
[ function(result) {] + CRLF
__lcHtml = __lcHtml + [ // Update the progress bar settings]+ CRLF +;
[ UpdateProgressBar("Progress",result.percent,result.message);]+ CRLF +;
[ ]+ CRLF +;
[ if (result.cancelled)]+ CRLF +;
[ {]+ CRLF +;
[ alert('Operation cancelled on the server.');]+ CRLF +;
[ $('#btnStartProcessing').attr("disabled",false);]+ CRLF +;
[ $('#btnStopProcessing').attr("disabled",true);]+ CRLF +;
[ }]+ CRLF +;
[ else if (result.completed || result.percent >= 100)] + CRLF
__lcHtml = __lcHtml + [ ProcessComplete();]+ CRLF +;
[ else]+ CRLF +;
[ window.setTimeout( GetProgress, TimerInterval );]+ CRLF +;
[ });]+ CRLF +;
[}]+ CRLF +;
[function ProcessComplete()]+ CRLF +;
[{]+ CRLF +;
[ // *** pick up the final result]+ CRLF +;
[ Progress_Ajax.callMethod("ProcessComplete_Callback",[] + ']' + [,]+ CRLF +;
[ function(Result)] + CRLF
__lcHtml = __lcHtml + [ {]+ CRLF +;
[ $('#btnStartProcessing').attr("disabled",false);]+ CRLF +;
[ $('#btnStopProcessing').attr("disabled",true);]+ CRLF +;
[ $("#lblResult").html("<center>" + Result + "</center>");]+ CRLF +;
[ UpdateProgressBar('Progress',100,"Customer List Download complete");]+ CRLF +;
[ });]+ CRLF +;
[} ]+ CRLF +;
[</script>]+ CRLF +;
[]+ CRLF +;
[ ]
THIS.CTL0015 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0015")
THIS.CTL0015.Text = __lcHtml
THIS.AddControl(THIS.CTL0015)
THIS.CTL0016 = CREATEOBJECT("wwWebForm",THIS.Page,"CTL0016")
THIS.CTL0016.RenderType = 2
THIS.AddControl(THIS.CTL0016)
__lcHtml = []
__lcHtml = __lcHtml + []+ CRLF +;
[</body>]+ CRLF +;
[</html>]
THIS.CTL0017 = CREATEOBJECT("wwWebLiteral",THIS.Page,"CTL0017")
THIS.CTL0017.Text = __lcHtml
THIS.AddControl(THIS.CTL0017)
ENDFUNC
ENDDEFINE
Many thanks
![]()