最近由于工作原因,客户需要使用一个实时的进度条,翻阅了多处的资料,基于前人的经验,在其基础上完成了一个多线程Asp.Net进度条。进度条的基本构成,前台使用jquery的进度条,jquery确实是个很好的东西,从开始接触到现在越来越喜欢使用;中间的数据传输,由于我对.Net回调机制的了解,因此选用了回调技术进行数据交互,其他Ajax框架,jquery的Ajax都可以替代,这里主要完成的是初始化进度条、启动进度、读取进度信息、返回进度信息至前台显示;Excel模板生成类,主要工作为获取webservice数据,加载模板,生成xls,压缩xls等多步工作。
前台jquery的进度条生成这里就不多描述了,另外主要的工作触发信息交互响应,设置进度条信息。

前台JS
1
//启动生成报表
2
function btnBuildReport()
{
3
$(".progressbar").progression(
{
4
Current: 0,
5
Maximum: 100,
6
Background: '#FFFFFF',
7
TextColor: '#000000',
8
aBackground: '#FF0000',
9
aTextColor: '#FFFFFF',
10
BorderColor: '#000000',
11
Animate: false,
12
AnimateTimeOut: 3000,
13
Easing: 'linear'
14
});
15
$("#Btn_Start").attr(
{ disabled: "disabled" });
16
$("#Btn_Download").attr(
{ disabled: "disabled" });
17
$("#imgShowLoading").show();
18
startTimer();
19
}
20
//回调处理的全部过程
21
var timer;
22
var counter;
23
function startTimer()
{
24
counter = 0;
25
build();
26
timer= setInterval("build()",5000);
27
}
28
29
function stopTimer()
{
30
clearInterval(timer);
31
}
32
33
function build()
34
{
35
UpdateGrid(counter);
36
}
37
38
function UpdateGrid(args)
39
{
40
<%=Page.ClientScript.GetCallbackEventReference(Me,"args","OnShowResult","") %>
41
}
42
43
function OnShowResult(eventArgument, context)
44
{
45
try
46
{
47
var args=eventArgument.split('^');
48
counter=args[0];
49
//可能的计数器返回情况,1-100:更新进度条;-1,后台异常;其他抛出异常
50
if(counter>0 && counter<=100)
51
{
52
var tmpi=i;
53
$(".progressbar").progression(
{ Current: counter, Background: "#eee",Animate: true});
54
$("#infoText").html(args[1]);
55
i=tmpi;
56
57
if(counter==100)
58
{
59
stopTimer();
60
//预览版本的报告的路径
61
$("#PreviewFilePath").attr(
{ value: args[2] });
62
//将供正式下载的完整版本报告的路径 赋值给一个控件
63
$("#DownLoadFilePath").attr(
{ value: args[3] });
64
//开放预览区域
65
document.getElementById("DIV_Preview").style.display = "";
66
67
//显示预览xls
68
PreviewXLS();
69
//开放启动、下载按钮(正式启用时,启动按钮应该屏蔽)
70
$("#Btn_Start").attr(
{ disabled: "" });
71
$("#Btn_Download").attr(
{ disabled: "" });
72
$("#imgShowLoading").hide();
73
}
74
}
75
else if(counter==-1||counter==-2)
76
{
77
//错误信息:-1为基础错误;-2为网络数据加载错误
78
//显示后台异常,2种方式,1为error显示,2为弹出显示
79
//将网络错误和其他错误最好能区分开
80
stopTimer();
81
if(counter==-1)
82
window.location = "Error.aspx?message="+args[1];
83
else
84
{
85
window.location = "Error.aspx?message="+args[1];
86
//运行用户再次获取数据,全部返回初始
87
$("#Btn_Start").attr(
{ disabled: "" });
88
$(".progressbar").progression(
{
89
Current: 0,
90
Maximum: 100,
91
Background: '#FFFFFF',
92
TextColor: '#000000',
93
aBackground: '#FF0000',
94
aTextColor: '#FFFFFF',
95
BorderColor: '#000000',
96
Animate: false,
97
AnimateTimeOut: 3000,
98
Easing: 'linear'
99
});
100
$("#infoText").html('');
101
$("#imgShowLoading").hide();
102
}
103
}
104
else
105
{
106
stopTimer();
107
window.location = "Error.aspx?message="+args[1];
108
}
109
110
}
111
catch(ex)
112
{
113
stopTimer();
114
window.location = "Error.aspx?message=Error Occurred.. Please try again..";
115
}
116
}
这样就完成了整个事件进程的监控和控制,后台处理相对来说基本和之前进度条处理的模式一致,首先启动时,定义一个线程运行,然后在后台设置一个静态变量存储进度条信息,由线程同步该静态变量。这种处理方式在并发用户时由于使用同一静态变量将产生并发冲突,无法正常显示每一个并发用户的处理情况。这里我只进行了一点点小小的改动,使之基本满足并发处理的要求,这里将原有的静态变量改为静态变量数据,将其与Session挂钩,在启动进程时,判断可用数组的位置,将其序号存放入Session中,并将其传入进程,使用数组配合Session达到并发处理的要求,这里可以根据数组的大小来确定并发响应数量。基本的代码如下:

后台
1 //静态数组
2 private static int[] currentProgress = new int[100];
3 private static string[] InfoText = new string[100];
4 //初始化状态,选择可用数组
5 {
6 for (int j = 0; j <= currentProgress.Length - 1; j++) {
7 if (currentProgress(j) == 0) {
8 Session("currentProgress") = j;
9 break; // TODO: might not be correct. Was : Exit For
10 }
11 }
12 }
13 //初始化,业务处理类
14 {
15 var xls = new ExcelHelper(currentProgress, InfoText, Session("currentProgress"));
16 xls.CustomizedReportName = Session("CustomizedReportName");
17 xls.Maximum = Maximum;
18 xls.strQuery = Session("");
19
20 //定义一个进程
21 System.Threading.Thread FillingExcelThread = new System.Threading.Thread(xls.FillingSpreadsheet);
22 try {
23 FillingExcelThread.Start();
24 }
25 catch (Exception ex) {
26 FillingExcelThread.Abort();
27 throw ex;
28 }
29 }
30 //后台获取进度信息
31 int currPro = currentProgress(Session("currentProgress"));
我们的业务线程处理类其实就只需要接收数组信息,然后在需要改变进程的地方处理数组内容即可由后台获取该进度信息返回值前台显示。
整体的思路应该还是众多前人提供的方法思路一致,主要是通过了静态数组和Session的方式,使其更好的处理并发用户状况。如还有更好的方案,借此进行一个沟通和交流。