在asp.net中执行一个长时间的操作,有的时候需要在在客户端有一个反馈能了解到任务的执行进度,大致看了一下有这么几种做法:
(1)按下按钮的时候给出一个<div>提示正在执行任务,执行完毕让这个<div>隐藏
(2)按下按钮的时候跳转到一个提示任务正在执行的页面,执行完毕了再跳转回来
(3)做一个任务类,开启另外一个线程执行任务,同时在客户端或者服务器端保存这个类的实例来跟踪任务的执行情况
(1)和(2)的情况用的比较多,也比较简单,缺点是不能实时的知道任务的执行进度,而且时间一长可能会超时,(3)的方法就会比较好的解决上面说的2个缺点。下面着重说一下(3)的实现方法,先从简单开始,我们做一个任务类,在客户端时时(暂且刷新时间为1秒)得知任务执行了多少时间,并且在成功完成任务后给出执行时间,在任务出错的时候给出出错的时间。
前台
<form id="form1" method="post" runat="server">
<asp:label id="lab_state" runat="server"></asp:label><br>
<asp:button id="btn_startwork" runat="server" text="运行一个长时间的任务"></asp:button>
</form>
后台
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace test20061027
{
/// <summary>
/// WebForm1 的摘要说明。
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button btn_startwork;
protected System.Web.UI.WebControls.Label lab_state;
protected work w;
private void Page_Load(object sender, System.EventArgs e)
{
if(Session["work"]==null)
{
w=new work();
Session["work"]=w;
}
else
{
w=(work)Session["work"];
}
switch(w.state)
{
case 0:
{
this.lab_state.Text="还没有开始任务";
break;
}
case 1:
{
this.lab_state.Text="任务进行了"+((TimeSpan)(DateTime.Now-w.starttime)).TotalSeconds+"秒";
this.btn_startwork.Enabled=false;
Page.RegisterClientScriptBlock("","<script>window.settimeout('location.href=location.href',1000);</script>");
//不断的刷新本页面,随时更新任务的状态
break;
}
case 2:
{
this.lab_state.Text="任务结束,并且成功执行所有操作,用时"+((TimeSpan)(w.finishtime-w.starttime)).TotalSeconds+"秒";
this.btn_startwork.Enabled=true;
break;
}
case 3:
{
this.lab_state.Text="任务结束,在"+((TimeSpan)(w.errortime-w.starttime)).TotalSeconds+"秒的时候发生错误导致任务失败";
this.btn_startwork.Enabled=true;
break;
}
}
}
#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.btn_startwork.Click += new System.EventHandler(this.btn_startwork_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void btn_startwork_Click(object sender, System.EventArgs e)
{
if(w.state!=1)
{
this.btn_startwork.Enabled=false;
w.runwork();
Page.RegisterClientScriptBlock("","<script>location.href=location.href;</script>");
}
}
}
}
另外建立一个任务类,代码如下:
using System;
using System.Threading;
using System.Data.SqlClient;
namespace test20061027
{
/// <summary>
/// work 的摘要说明。
/// </summary>
public class work
{
public work()
{
}
public int state=0; //0-没有开始,1-正在运行,2-成功结束,3-失败结束
public DateTime starttime;
public DateTime finishtime;
public DateTime errortime;
public void runwork()
{
lock(this)
{
if(this.state !=1)
{
this.state = 1;
this.starttime = System.DateTime.Now;
System.Threading.Thread thread = new Thread(new System.Threading.ThreadStart(dowork));
thread.Start();
}
}
}
private void dowork()
{
try
{
SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["ConnectionSqlServer"]);
System.Data.SqlClient.SqlCommand cmd = new SqlCommand("insert into Test (test)values('test')",conn);
conn.Open();
for(int i=0;i<5000;i++)cmd.ExecuteNonQuery();
conn.Close();
state=2;
}
catch
{
errortime=DateTime.Now;
state=3;
}
finally
{
finishtime=DateTime.Now;
}
}
}
}
