The following describes how to use static variables:
Copy codeThe Code is as follows: <% @ Page Language = "C #" %>
<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional. dtd">
<Script runat = "server">
Private static int Processbar = 0;
Private static int TotalCount = 100; // set the initial value to prevent division by 0.
Protected void ProcessTask ()
{
// Calculate the TotalCount value, such as querying the database.
TotalCount = 150;
While (Processbar <TotalCount)
{
Processbar + = 5;
System. Threading. Thread. Sleep (1000 );
}
}
Protected void Page_Load (object sender, EventArgs e)
{
If (Request. QueryString ["step"]! = Null & Request. QueryString ["step"]. Equals (String. Empty) = false)
{
If (Request. QueryString ["step"]. Equals ("1 "))
{
Processbar = 0;
System. Threading. Thread thread = new System. Threading. Thread (new System. Threading. ThreadStart (ProcessTask ));
Thread. Start ();
Response. ClearContent ();
Response. Write (0 );
Response. End ();
}
Else
{
Response. ClearContent ();
If (Processbar <TotalCount)
{
Response. Write (procw.ar * 100/TotalCount );
}
Else
{
Response. Write ("OK ");
}
Response. End ();
}
}
}
</Script>
<Html xmlns = "http://www.w3.org/1999/xhtml">
<Head runat = "server">
<Title> view the progress bar of server-side task processing on the client </title>
<Script type = "text/javascript">
Var http = null;
Var count = 1;
Var timer = null;
Function createXMLHTTP (){
Return window. XMLHttpRequest? New window. XMLHttpRequest (): new window. ActiveXObject ("MSXML2.XMLHTTP ");
}
Function showProcess (){
Http = createXMLHTTP ()
Http. open ("GET", "<% = Request. Url. ToString () %>? Step = "+ (count ++) +" & "+ Date. parse (new Date (), true );
Http. onreadystatechange = function (){
If (http. readyState = 4 & http. status = 200)
If ("OK" = http. responseText ){
Document. getElementById ("process"). innerHTML = "complete ";
Window. clearInterval (timer );
}
Else {
Document. getElementById ("process"). innerHTML = http. responseText + "% ";
}
}
Http. send (null );
}
Function startTask (){
Count = 1;
Document. getElementById ("process"). innerHTML = "0% ";
Timer = window. setInterval ("showProcess ()", 1000 );
Return false;
}
</Script>
</Head>
<Body>
<Form id = "form1" runat = "server">
<Input type = "button" value = "start to process long-time operations" onclick = "return startTask ();"/>
<Div id = "process"> </div>
</Form>
</Body>
</Html>
In this way, there is no problem when one user accesses it, but it will cause confusion when multiple users access it.
The following method is a common method that can meet the requirements in general:Copy codeThe Code is as follows: <% @ Page Language = "C #" %>
<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
Transitional. dtd ">
<Script runat = "server">
/// <Summary>
/// Set global variables so that different methods use
/// </Summary>
Private int Processbar = 0; // set the initial state, which can also represent each step in a series of steps.
Private int TotalCount = 100; // set the initial value to prevent division by 0.
Private String key;
Protected void ProcessTask ()
{
While (Processbar <TotalCount)
{
Processbar = this. GetProcessbar () + 5; // here, it is just a simulation.
System. Threading. Thread. Sleep (1000); // It only simulates a long execution process.
SaveData ();
}
}
Protected void Page_Load (object sender, EventArgs e)
{
Key = Request. QueryString ["guid"]; // identifies a client Request when multiple concurrent requests exist.
If (String. IsNullOrEmpty (key) key = Guid. NewGuid (). ToString ();
Processbar = this. GetProcessbar ();
TotalCount = this. GetTotalCount ();
// The following Code determines whether the request is the first request or the update progress bar. The implementation method can also be divided into multiple programs.
If (Request. QueryString ["step"]! = Null & Request. QueryString ["step"]. Equals (String. Empty) = false)
{
If (Request. QueryString ["step"]. Equals ("1 "))
{
// A request to start executing a task and start processing a task for a long time.
Processbar = 0;
// Calculate the TotalCount value, such as querying the database. It can also be the sum of multiple steps of a task.
TotalCount = 200; // It takes 200 steps to complete a task
SaveData ();
System. Threading. Thread thread = new System. Threading. Thread (new System. Threading. ThreadStart (ProcessTask ));
Thread. Start ();
Response. ClearContent ();
Response. Write (0 );
Response. End ();
}
Else
{
Response. ClearContent ();
If (Processbar <TotalCount)
{
// Process of Output Processing
Response. Write (procw.ar * 100/TotalCount );
}
Else
{
// All tasks are completed, and the end information is output to terminate the frontend request.
Response. Write ("OK ");
Cache. Remove (key );
}
Response. End ();
}
}
Else
{
G. Text = key;
If (System. IO. File. Exists (Server. MapPath (key + ". txt ")))
{
System. IO. File. Delete (Server. MapPath (key + ". txt "));
}
}
}
/// <Summary>
/// Get the stage of the execution process
/// </Summary>
/// <Returns> </returns>
Private int GetProcessbar ()
{
String data = Convert. ToString (Cache. Get (key ));
If (String. IsNullOrEmpty (data ))
Return 0;
Else
{
Return Convert. ToInt32 (data. Split (',') [0]);
}
}
/// <Summary>
/// Obtain the total number of processes
/// </Summary>
/// <Returns> </returns>
Private int GetTotalCount ()
{
String data = Convert. ToString (Cache. Get (key ));
If (String. IsNullOrEmpty (data ))
Return 0;
Else
{
Return Convert. ToInt32 (data. Split (',') [1]);
}
}
/// <Summary>
/// Save the process.
/// </Summary>
Private void SaveData ()
{
WriteLog ();
Cache. Insert (key, Processbar. ToString () + "," + TotalCount. ToString ());
}
Private void WriteLog ()
{
System. IO. StreamWriter sw = new System. IO. StreamWriter (Server. MapPath (key + ". txt"), true );
Sw. WriteLine ("Processbar =" + Processbar + "TotalCount =" + TotalCount + "" + System. DateTime. Now. ToString
());
Sw. Close ();
}
</Script>
<Html xmlns = "http://www.w3.org/1999/xhtml">
<Head id = "Head1" runat = "server">
<Title> view the progress bar of server-side task processing on the client </title>
<Script type = "text/javascript">
Var http = null;
Var count = 1;
Var timer = null;
Var guid = "<asp: Literal id = 'G' runat = 'server'/> ";
Function createXMLHTTP (){
Return window. XMLHttpRequest? New window. XMLHttpRequest (): new window. ActiveXObject ("MSXML2.XMLHTTP ");
}
Function showProcess (){
Http = createXMLHTTP ();
Http. open ("GET", "<% = Request. Url. ToString () %>? Step = "+ (count ++) +" & guid = "+ guid +" & "+ Date. parse (new
Date (), true );
Http. setRequestHeader ("Connection", "close ");
Http. onreadystatechange = function (){
If (http. readyState = 4 & http. status = 200)
If ("OK" = http. responseText ){
Document. getElementById ("process"). innerHTML = document. getElementById ("processbar1"). innerHTML = "complete ";
Document. getElementById ("processbar2"). style. width = "100% ";
Window. clearInterval (timer );
}
Else {
Document. getElementById ("process"). innerHTML = document. getElementById ("processbar1"). innerHTML =
Http. responseText + "% ";
Document. getElementById ("processbar2"). style. width = http. responseText + "% ";
}
}
Http. send (null );
}
Function startTask (){
Count = 1;
Document. getElementById ("process"). innerHTML = document. getElementById ("processbar1"). innerHTML = "0% ";
Document. getElementById ("processbar2"). style. width = "0% ";
Timer = window. setInterval ("showProcess ()", 1000 );
Return false;
}
</Script>
</Head>
<Body>
<Form id = "form1" runat = "server">
<Input type = "button" value = "start to process long-time operations" onclick = "return startTask ();"/>
<Div style = "border: 1px solid blue; width: 600px; position: relative; margin: 10px 0;">
<Div style = "background: # f00; width: 0; height: 20px;" id = "processbar2"> </div>
<Div style = "position: absolute; text-align: center; top: 0; width: 100%" id = "processbar1"> </div>
</Div>
<Div id = "process"> </div>
</Form>
</Body>
</Html>
Code execution result:
But is this a perfect solution? Completely incorrect. This method is still inaccurate. The cause of inaccurate display is the use of Cache. After IIS 6, the application pool function is added, this function can greatly improve the program performance and reduce the failure of the entire website caused by program errors. However, if the number of "performance"-"Web Parks" in the Application pool is greater than 1, HttpApplicationState (Application), Cache, and HttpSessionState (Session) these variables are all unusable because every Web garden starts a w3wp.exe Worker Process, and each worker process is independent of each other. Therefore, the method for saving the program execution progress using the Cache is not completely correct.
So what is the ultimate method? Yes, you can save the program execution progress on a third-party storage medium, such as databases and file systems. I will not write the code for this method, that is, add access to the database.