您的位置:首页 > 编程语言 > ASP

asp.net 在客户端显示服务器端任务处理进度条的探讨

2009-09-12 00:00 676 查看
下面就是采用静态变量的方法实现的:
<%@ 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; //设置初始值,防止出现被0除。 
protected void ProcessTask() 
{ 
//通过计算,得出TotalCount的值,比如查询数据库等 
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(Processbar * 100 / TotalCount); 
} 
else 
{ 
Response.Write("ok"); 
} 
Response.End(); 
} 
} 
} 
</script> 

<html xmlns="http://www.w3.org/1999/xhtml "> 
<head runat="server"> 
<title>在客户端显示服务器端任务处理进度条的探讨</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 = "完成"; 
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="开始处理长时间操作" onclick="return startTask();" /> 
<div id="process"></div> 
</form> 
</body> 
</html>

这种方法,在一个用户访问的情况下是没有问题的,但多个用户访问时就会造成混乱。

下面这这种方法,是常用的方法,一般情况下可以满足需求:
<%@ 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> 
/// 设置全局变量,以便不同的方法是用 
/// </summary> 
private int Processbar = 0; //设置初始的状态,也可以代表一系列步骤中的每个步骤。 
private int TotalCount = 100; //设置初始值,防止出现被0除。 
private String key; 
protected void ProcessTask() 
{ 
while (Processbar < TotalCount) 
{ 
Processbar = this.GetProcessbar() + 5; //这里只是模拟一下,每次加 5 
System.Threading.Thread.Sleep(1000); //这里只是模拟一个长时间的执行过程。 
SaveData(); 
} 
} 

protected void Page_Load(object sender, EventArgs e) 
{ 
key = Request.QueryString["guid"]; //多个并发请求时,用来区分客户端的请求。 
if (String.IsNullOrEmpty(key)) key = Guid.NewGuid().ToString(); 
Processbar = this.GetProcessbar(); 
TotalCount = this.GetTotalCount(); 

//以下判断原来判断请求的不同过程,是第一次请求,还是更新进度条的请求,实现方法也可以划分为多个程序来实现。 
if (Request.QueryString["step"] != null && Request.QueryString["step"].Equals(String.Empty) == false) 
{ 
if (Request.QueryString["step"].Equals("1")) 
{ 
// 开始执行任务的请求,启动长时间的任务处理。 
Processbar = 0; 
//通过计算,得出TotalCount的值,比如查询数据库等,也可以是一个任务的多个步骤的总和。 
TotalCount = 200; //假如完成一个任务需要200个步骤 
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) 
{ 
// 输出处理的过程 
Response.Write(Processbar * 100 / TotalCount); 
} 
else 
{ 
// 所有的任务都完成了,输出结束信息,终止前端的请求。 
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> 
/// 得到执行过程的阶段 
/// </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> 
/// 得到全部的过程数 
/// </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> 
/// 将过程保存。 
/// </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>在客户端显示服务器端任务处理进度条的探讨</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 = "完成"; 
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="启动处理长时间操作" 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>

代码执行效果:



但是,这种方法就是万事大吉了吗?完全错误,这种方法仍然存在显示不准确的现象,造成显示不准确的原因就是 Cache 的使用,IIS 6之后,增加了应用程序池的功能,这个功能可以大大提高程序的性能,减少程序本身的错误导致的整个网站的崩溃。但是,如果应用程序池的“性能”-“Web 园”数目设置大于1的情况下,HttpApplicationState(Application)、Cache、HttpSessionState(Session)这些变量都是都是无法使用了,这是因为:每个Web 园会启动一个w3wp.exe工作进程,每个工作进程之间是相互独立的,以上这些变量也就是不是共享的了,所以,使用Cache保存程序执行进度的方法也是不完全正确的。

那么终极的方法是什么呢?对,将程序执行进度保存在第三方的存储介质上,如数据库,文件系统等等都是可以的。这个方法代码我就不写了,就是增加访问数据库的部分即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐