asp.net 在客戶(hù)端顯示服務(wù)器端任務(wù)處理進(jìn)度條的探討
<%@ 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; //設(shè)置初始值,防止出現(xiàn)被0除。
protected void ProcessTask()
{
//通過(guò)計(jì)算,得出TotalCount的值,比如查詢(xún)數(shù)據(jù)庫(kù)等
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>在客戶(hù)端顯示服務(wù)器端任務(wù)處理進(jìn)度條的探討</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="開(kāi)始處理長(zhǎng)時(shí)間操作" onclick="return startTask();" />
<div id="process"></div>
</form>
</body>
</html>
這種方法,在一個(gè)用戶(hù)訪問(wèn)的情況下是沒(méi)有問(wèn)題的,但多個(gè)用戶(hù)訪問(wèn)時(shí)就會(huì)造成混亂。
下面這這種方法,是常用的方法,一般情況下可以滿(mǎn)足需求:
<%@ 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>
/// 設(shè)置全局變量,以便不同的方法是用
/// </summary>
private int Processbar = 0; //設(shè)置初始的狀態(tài),也可以代表一系列步驟中的每個(gè)步驟。
private int TotalCount = 100; //設(shè)置初始值,防止出現(xiàn)被0除。
private String key;
protected void ProcessTask()
{
while (Processbar < TotalCount)
{
Processbar = this.GetProcessbar() + 5; //這里只是模擬一下,每次加 5
System.Threading.Thread.Sleep(1000); //這里只是模擬一個(gè)長(zhǎng)時(shí)間的執(zhí)行過(guò)程。
SaveData();
}
}
protected void Page_Load(object sender, EventArgs e)
{
key = Request.QueryString["guid"]; //多個(gè)并發(fā)請(qǐng)求時(shí),用來(lái)區(qū)分客戶(hù)端的請(qǐng)求。
if (String.IsNullOrEmpty(key)) key = Guid.NewGuid().ToString();
Processbar = this.GetProcessbar();
TotalCount = this.GetTotalCount();
//以下判斷原來(lái)判斷請(qǐng)求的不同過(guò)程,是第一次請(qǐng)求,還是更新進(jìn)度條的請(qǐng)求,實(shí)現(xiàn)方法也可以劃分為多個(gè)程序來(lái)實(shí)現(xiàn)。
if (Request.QueryString["step"] != null && Request.QueryString["step"].Equals(String.Empty) == false)
{
if (Request.QueryString["step"].Equals("1"))
{
// 開(kāi)始執(zhí)行任務(wù)的請(qǐng)求,啟動(dòng)長(zhǎng)時(shí)間的任務(wù)處理。
Processbar = 0;
//通過(guò)計(jì)算,得出TotalCount的值,比如查詢(xún)數(shù)據(jù)庫(kù)等,也可以是一個(gè)任務(wù)的多個(gè)步驟的總和。
TotalCount = 200; //假如完成一個(gè)任務(wù)需要200個(gè)步驟
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)
{
// 輸出處理的過(guò)程
Response.Write(Processbar * 100 / TotalCount);
}
else
{
// 所有的任務(wù)都完成了,輸出結(jié)束信息,終止前端的請(qǐng)求。
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>
/// 得到執(zhí)行過(guò)程的階段
/// </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>
/// 得到全部的過(guò)程數(shù)
/// </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>
/// 將過(guò)程保存。
/// </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>在客戶(hù)端顯示服務(wù)器端任務(wù)處理進(jìn)度條的探討</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="啟動(dòng)處理長(zhǎng)時(shí)間操作" 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>
代碼執(zhí)行效果:

但是,這種方法就是萬(wàn)事大吉了嗎?完全錯(cuò)誤,這種方法仍然存在顯示不準(zhǔn)確的現(xiàn)象,造成顯示不準(zhǔn)確的原因就是 Cache 的使用,IIS 6之后,增加了應(yīng)用程序池的功能,這個(gè)功能可以大大提高程序的性能,減少程序本身的錯(cuò)誤導(dǎo)致的整個(gè)網(wǎng)站的崩潰。但是,如果應(yīng)用程序池的“性能”-“Web 園”數(shù)目設(shè)置大于1的情況下,HttpApplicationState(Application)、Cache、HttpSessionState(Session)這些變量都是都是無(wú)法使用了,這是因?yàn)椋好總€(gè)Web 園會(huì)啟動(dòng)一個(gè)w3wp.exe工作進(jìn)程,每個(gè)工作進(jìn)程之間是相互獨(dú)立的,以上這些變量也就是不是共享的了,所以,使用Cache保存程序執(zhí)行進(jìn)度的方法也是不完全正確的。
那么終極的方法是什么呢?對(duì),將程序執(zhí)行進(jìn)度保存在第三方的存儲(chǔ)介質(zhì)上,如數(shù)據(jù)庫(kù),文件系統(tǒng)等等都是可以的。這個(gè)方法代碼我就不寫(xiě)了,就是增加訪問(wèn)數(shù)據(jù)庫(kù)的部分即可。
- ASP.NET實(shí)現(xiàn)進(jìn)度條效果
- asp.net mvc 實(shí)現(xiàn)文件上傳帶進(jìn)度條的思路與方法
- asp.net文件上傳帶進(jìn)度條實(shí)現(xiàn)案例(多種風(fēng)格)
- asp.net單文件帶進(jìn)度條上傳的解決方案
- Asp.Net 無(wú)刷新文件上傳并顯示進(jìn)度條的實(shí)現(xiàn)方法及思路
- asp.net(c#)開(kāi)發(fā)中的文件上傳組件uploadify的使用方法(帶進(jìn)度條)
- asp.net 生成靜態(tài)頁(yè)時(shí)的進(jìn)度條顯示
- Asp.net基于ajax和jquery-ui實(shí)現(xiàn)進(jìn)度條
相關(guān)文章
使用Fiddler調(diào)試visual studion多個(gè)虛擬站點(diǎn)的問(wèn)題分析
本篇文章小編為大家介紹,使用Fiddler調(diào)試visual studion多個(gè)虛擬站點(diǎn)的問(wèn)題分析。需要的朋友參考下2013-04-04ASP.NET泛型一之泛型簡(jiǎn)介與基本語(yǔ)法
這篇文章介紹了ASP.NET泛型的簡(jiǎn)介與基本語(yǔ)法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Visual studio 2017如何發(fā)布dotnet core到docker
這篇文章主要介紹了Visual studio 2017如何發(fā)布dotnet core到docker的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04c# static 靜態(tài)數(shù)據(jù)成員
靜態(tài)成員屬于類(lèi)所有,為各個(gè)類(lèi)的實(shí)例所公用,無(wú)論類(lèi)創(chuàng)建了幾多實(shí)例,類(lèi)的靜態(tài)成員在內(nèi)存中只占同一塊區(qū)域。2009-06-06c# NameValueCollection類(lèi)讀取配置信息
c#中的NameValueCollection類(lèi)讀取配置信息,大家可以參考下。2009-04-04如何在ASP.NET Core類(lèi)庫(kù)項(xiàng)目中讀取配置文件詳解
這篇文章主要給大家介紹了關(guān)于如何在ASP.NET Core類(lèi)庫(kù)項(xiàng)目中讀取配置文件的相關(guān)資料,這是朋友提的一個(gè)問(wèn)題,文中通過(guò)示例代碼介紹的非常詳解,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。2017-10-10ASP.NET文件上傳Upload的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了ASP.NET文件上傳的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11ASP.NET讓FileUpload控件支持瀏覽自動(dòng)上傳功能的解決方法
這篇文章主要介紹了ASP.NET讓FileUpload控件支持瀏覽自動(dòng)上傳功能的解決方法,很實(shí)用的技巧,需要的朋友可以參考下2014-07-07asp.net 讀取文本文件并插入數(shù)據(jù)庫(kù)的實(shí)現(xiàn)代碼
最近我司和招行有合作,招行給財(cái)務(wù)的是一個(gè)txt格式的賬務(wù)文本文件,文本文件包含很多內(nèi)容,對(duì)賬只需要用到其中一部分內(nèi)容。2010-04-04Asp.Net 網(wǎng)站性能優(yōu)化之緩字決 (上) 緩沖寫(xiě)數(shù)據(jù)
通常情況下Asp.Net 網(wǎng)站的底層數(shù)據(jù)存儲(chǔ)都是關(guān)系數(shù)據(jù)庫(kù),關(guān)系數(shù)據(jù)庫(kù)資源比較昂貴,而且也很容易造成瓶頸。緩字決文章就是為大家介紹如何有效使用緩存,異步寫(xiě)緩沖數(shù)據(jù)庫(kù)的壓力,從而保證網(wǎng)站的性能。2010-06-06