ExtJS+ASP.NET实现真实的进度条显示服务器端长时间操作的进度

当服务器端执行一个长时间的操作时,页面上如何显示一个反应真实的进度条,报告服务器端执行耗时操作的进度,而不是让用户永远等待,这对用户来说是非常有用的,能够有效提高用户体验(参见《用户体验这点事儿》)。这篇文章使用AJAX,ASP.NET和ExtJS实现这个功能。

saving

实现过程大概如下:

其中第4步是采用客户轮询获得服务器端操作进度的方法,而不是服务器端主动通知(Push模式)客户端,这点注意。使用ExtJS是因为其封装了很好的客户端JS进度条控件,非常方便使用。下面就是具体的分步实现:

改造服务器端耗时操作的WebService,保存当前进度在Context

 1: using System.Threading;
 2: using System.Web;
 3: using System.Web.Security;
 4:  
 5: public bool ExecuteTimeConsumingTask()
 6: {
 7: string processKey = HttpContext.Current.Request.UserHostAddress;
 8: string threadLockKey = "thread" + HttpContext.Current.Request.UserHostAddress;
 9: object threadLock = HttpContext.Current.Cache[threadLockKey];
 10:  
 11: if (threadLock == null)
 12: {
 13: threadLock = new object();
 14: HttpContext.Current.Cache[threadLockKey] = threadLock;
 15: }
 16:  
 17: // Only allow 1 running task per user.
 18: if (!Monitor.TryEnter(threadLock, 0))
 19: return false;
 20:  
 21: int LEN = 1000;
 22:  
 23: int i = 0;
 24:  
 25: for (int i = 0; i < LEN; i++)
 26: {
 27: //DO Something here...
 28:  
 29: //把进度保存在用户的ContextCache中
 30: HttpContext.Current.Cache[processKey] = i * 100 / LEN;
 31: }
 32:  
 33: Monitor.Exit(threadLock);
 34: return true;
 35: }

服务器端提供另一个WebService以供客户端查询上述操作的当前进度

 1: public int GetTaskProgress()
 2: {
 3: string processKey = HttpContext.Current.Request.UserHostAddress;
 4: object progress = HttpContext.Current.Cache[processKey];
 5:  
 6: if (progress != null)
 7: {
 8: return (int)progress;
 9: }
 10: return 0;
 11: }

客户端操作,包括JS轮询服务器端WebService查询进度(异步)并更新进度条等

 1: var currentProgress = 0;
 2:  
 3: //显示进度条
 4: ShowProgressbar(); 
 5:  
 6: //触发执行长时间操作的WebService
 7: myService.ExecuteTimeConsumingTask(successCallback, failCallback);
 8:  
 9: //显示进度条,轮询服务器长时间操作的进度,并更新进度条
 10: function ShowProgressbar(){
 11: currentProgress = 0;
 12: 
 13: Ext.MessageBox.show({
 14: title: '请稍等...',
 15: msg: '服务器端正在处理 ...',
 16: progressText: '初始化...',
 17: width:300,
 18: progress:true,
 19: closable:false,
 20: animEl: 'mb6'
 21: });
 22:  
 23: function f(){
 24: if(currentProgress < 100)
 25: {
 26: //触发查询服务器端进度的WebService
 27: //查询服务器长时间操作的进度,异步,在callback中检查返回值并更新进度条
 28: myService.GetTaskProgress(getProcressSuccessCallback, failCallback);
 29: 
 30: //循环调用,使得轮询效果
 31: setTimeout(f, 1000); 
 32: }
 33: };
 34: //开始轮询
 35: setTimeout(f, 1000);
 36: }
 37:  
 38: //回调函数,从服务器端WebService取得长时间操作的进度, 并更新进度条
 39: function getProcressSuccessCallback(result){
 40: if(currentProgress >= 100) return; //已完成,注意是异步的长时间操作
 41: 
 42: currentProgress = result;
 43: 
 44: if(result >= 100){
 45: Ext.MessageBox.hide();
 46: }else{
 47: var i = result/100;
 48: Ext.MessageBox.updateProgress(i, Math.round(100*i)+'% 已完成');
 49: } 
 50: }
 51: 
 52: //回调函数,长时间操作执行完成
 53: function successCallback(result){
 54: if (result == true) 
 55: alert('任务成功完成');
 56: else
 57: alert('任务失败');
 58: 
 59: //设置进度完成,可能异步先返回
 60: currentInd = 100;
 61: 
 62: //隐藏进度条
 63: if(Ext.MessageBox.isVisible()) 
 64: Ext.MessageBox.hide();
 65: }

或许您对以下相关文章有兴趣:

posted on 2009-04-27 15:49  Mainz  阅读(6836)  评论(14编辑  收藏  举报

导航