ASP.net实现WEB站点的后台定时任务

news/2024/7/10 1:06:55 标签: asp.net, web, 任务, web服务, null, 磁盘
采用Asp.net的定时处理方式,在WEB服务器层处理业务
核心处理就是System.Threading.Timer。这个定时类可以用于在后台定时执行用户提交操作, 


它的使用方法:

System.Threading.TimerCallback t
= new  System.Threading.TimerCallback (你的处理方法);
System.Threading.Timer t 
=   new  System.Threading.Timer(t, null , 1000 , 5000 );
 这一段说明是在启动1秒后每隔5秒就调用所指定的代理。

在具体实现时我定义了三个类。 

1 、BkExecItem用于保存用户提交操作,同时它也可以序列化到磁盘上,以免关键后台任务丢失。 

2 、BkExec用于执行。它通过反射来调用BkExecItem中所指定的方法。另外它中间还维护一个先入 

先出队列Queue
< BkExecItem > ,这个队列记录全部的后台处理项。 

3 、BkManager完成定时器的初始化,模块的参数配置等功能。 

呵,暂时总结到这里。下次我会将代码也贴上来,供大家参考下。

一个实用ASP.Net 后台处理类 

呵.这回跟大家讨论下ASP.net 后台处理 ,并会把我们当前项目中应用的一个后台处理类的代码贴上来参考. 

后台处理也是现在管理系统设计中需要考虑到的一个问题. 

什么是后台处理,可以简单认为不是在用户进程处理中完成用户提交的操作,而是将这一处理放到服务端后台进程来处理. 

加入后台处理后,可以提高前台用户的操作速度,改善用户操作体验. 

对于一般用户来说他对于一个系统的基本要求就是响应及时,用户很难对一个提交操作后需要等待10秒以后的管理系统产生好感,但在实际系统运行中用户操作是很难在短时间内得到响应,所以这个时候后台处理就可以发挥作用了. 

我在后面所帖代码中,将需要后台处理的任务均定义成一个ExecItem对象.用户提交操作后,系统将就操作转成一个ExecItem对象加入到BkExecManager(后台处理管理对象)中的一个先入先出的队列中. 

网站在启动时会自动启动BkExecManager,而BkExecManager则启动一个定时器来定时处理后台任务队列. 

在处理完成时BkExecManager就队列中移去任务对象,如果操作失败将以邮件方式通知管理员来完成问题处理. 

呵.现在贴代码
!  

1 ,后台处理管理对象 

 

public   class  BkExecManager
{  
    
//定时回调。
    private static TimerCallback timerDelegate;
    
private static Timer stateTimer;
    
private static BkExecer m_Execer;
    
public static string DataPath;
    
public static string BkManager = "XXXX";
    
public static int BkBufSize = 100;
    
private static int Interval = 10000;

    
public static BkExecer Execer
    
{
        
get return m_Execer; }
    }


    
static BkExecManager()
    
{
        DataPath 
= System.AppDomain.CurrentDomain.BaseDirectory + "BkItem/";
        
if (System.Configuration.ConfigurationManager.AppSettings["Interval"!= null)
            Interval 
= Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Interval"]);

        
if (System.Configuration.ConfigurationManager.AppSettings["BkBufSize"!= null)
            BkBufSize 
= Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["BkBufSize"]);

        
if (System.Configuration.ConfigurationManager.AppSettings["BkManager"!= null)
            BkManager 
= System.Configuration.ConfigurationManager.AppSettings["BkManager"];

        m_Execer 
= new BkExecer();
        
//初始化回调
        timerDelegate = new TimerCallback(m_Execer.DoBkExec);
        
//初始化定时器
        stateTimer = new Timer(timerDelegate, null5000, Interval);
    }


    
/**//// <summary>
    
/// 停止定时器.
    
/// </summary>

    static void BkExecQuit()
    
{
        stateTimer.Dispose();
    }

}

2 ,后台处理执行 

 

public   class  BkExecer
{
    
//维护一个前进前出的队列。
    private Queue<ExecItem> m_BkExecItemList;
    
private static object lockHelper = new object();
    
private static bool m_IsBusy = false;

    
public static bool IsBusy
    
{
        
get return m_IsBusy; }
    }


    
public BkExecer()
    
{
        m_BkExecItemList 
= new Queue<ExecItem>(BkExecManager.BkBufSize);
        
/**/////读入待处理事项
        InitData();
    }


    
private void InitData()
    
{
        
lock (lockHelper)
        
{
            
string[] fnl = Directory.GetFiles(BkExecManager.DataPath);
            
foreach (string s in fnl)
            
{
                
if (!s.Contains(BKExecItemState.出错.ToString()))
                
{
                    ExecItem ei 
= ExecItem.GetObject(s);
                    m_BkExecItemList.Enqueue(ei);
                }

            }

        }

    }


    
public void AddBkExecItem(ExecItem ei)
    
{
        
lock (lockHelper)
        
{
            
//锁定资源。
            m_BkExecItemList.Enqueue(ei);
        }

    }


    
public void DoBkExec(object Msg)
    
{
        ExecItem ei;
        
while (m_BkExecItemList.Count > 0)
        
{
            
lock (lockHelper)
            
{
                ei 
= m_BkExecItemList.Dequeue();
            }


            
int rv = -1;
            
try
            
{
                BindingFlags flags 
= BindingFlags.InvokeMethod | BindingFlags.Instance |
                BindingFlags.Public 
| BindingFlags.Static;
                
object t = ei.ExecItemClass.InvokeMember(ei.ExecItemMethed, flags, 
                    
nullnull, ei.ExecItemParamList);

                
if (t != null)
                    rv 
= Convert.ToInt32(t);
                
else
                    rv 
= 0;     //如果是无返回则直接设置零.
            }

            
catch (Exception e)
            
{
                
//更新Ei的状态,保存到磁盘
                ei.FinishBkExec(false, e.Message);
            }

            
finally
            
{
                
//更新Ei的状态,删除存件
                
//保存到磁盘
                if (rv >= 0)
                    ei.FinishBkExec(
true"");
                
else
                    ei.FinishBkExec(
false, rv.ToString());
            }

        }

    }

}

3 ,任务对象 


public   enum  BKExecItemState  { 待执行, 完成, 出错 } ;

[Serializable]
/**/ /// <summary>
/// 后台命令集合
/// 直接将这些后台命令二进制序列化到WEb服务器上保存。
/// 如果完成后则从Web服务器上删除。
/// 如果异常则发邮件通知管理员。
/// </summary>

public   class  ExecItem
{
    
/**//// <summary>
    
/// 磁盘文档名称 。
    
/// </summary>

    private string BKStoreFileName = "";
    
private string ErrMsg = "";
    
private BKExecItemState m_ItemState;

    
public BKExecItemState ItemState
    
{
        
get return m_ItemState; }
    }


    
private DateTime m_ExecItemExecTime;
    
public DateTime ExecItemExecTime
    
{
        
get return m_ExecItemExecTime; }
    }


    
private DateTime m_ExecItemCreateTime;
    
public DateTime ExecItemCreateTime
    
{
        
get return m_ExecItemCreateTime; }
    }


    
private string m_ExecItemName;
    
public string ExecItemName
    
{
        
get return m_ExecItemName; }
    }


    
private Type m_ExecItemClass;
    
public Type ExecItemClass
    
{
        
get return m_ExecItemClass; }
    }

    
private string m_ExecItemMethed;
    
public string ExecItemMethed
    
{
        
get return m_ExecItemMethed; }
    }


    
private object[] m_ExecItemParamList;
    
public object[] ExecItemParamList
    
{
        
get return m_ExecItemParamList; }
    }


    
private string m_Op;
    
/**//// <summary>
    
/// 后台任务对象
    
/// </summary>
    
/// <param name="objtype">对象类型</param>
    
/// <param name="ExecMethod">调用方法</param>
    
/// <param name="param">调用参数</param>
    
/// <param name="ExecName">任务</param>
    
/// <param name="Op">提交人</param>
    
/// <param name="SavetoDisk">是否保存到磁盘</param>

    public ExecItem(Type objtype, string ExecMethod, object[] param, string ExecName, string Op, bool SavetoDisk)
    
{
        
this.BKStoreFileName = String.Format("{0} {1} {2}.bin",
            DateTime.Now.ToString(
"yyyy-MM-dd HH-mm-ss"), ExecMethod, Op);

        
this.m_ExecItemClass = objtype;
        
this.m_ExecItemCreateTime = DateTime.Now;
        
this.m_ExecItemExecTime = DateTime.Now;
        
this.m_ExecItemMethed = ExecMethod;
        
this.m_ExecItemName = ExecName;
        
this.m_ExecItemParamList = param;
        
this.m_ItemState = BKExecItemState.待执行;
        
this.m_Op = Op;

        
if (SavetoDisk)
            SaveToDisk();
    }


    
private void SaveToDisk()
    
{
        IFormatter formatter 
= new BinaryFormatter();
        Stream stream 
= new FileStream(BkExecManager.DataPath + BKStoreFileName, 
            FileMode.Create, FileAccess.Write, FileShare.None);
        formatter.Serialize(stream, 
this);
        stream.Close();
    }


    
private void SaveToDisk2()
    
{
        
//
        string basedir = System.AppDomain.CurrentDomain.BaseDirectory;
        
this.BKStoreFileName = String.Format("{0} {1} {2} {3}.bin",
            m_ExecItemCreateTime.ToString(
"yyyy-MM-dd HH-mm-ss"), 
            
this.m_ExecItemMethed,
            m_Op, 
            m_ItemState.ToString());

        IFormatter formatter 
= new BinaryFormatter();
        Stream stream 
= new FileStream(BkExecManager.DataPath + BKStoreFileName,
            FileMode.Create, FileAccess.Write, FileShare.None);
        formatter.Serialize(stream, 
this);
        stream.Close();
    }


    
public static ExecItem GetObject(string s)
    
{
        IFormatter formatter 
= new BinaryFormatter();
        Stream stream 
= new FileStream(s, FileMode.Open, FileAccess.Read, FileShare.None);
        ExecItem e 
= (ExecItem) formatter.Deserialize(stream);
        stream.Close();
        
return e;
    }


    
public void FinishBkExec(bool DoneOk, string Msg)
    
{
        
string FileName = BkExecManager.DataPath + BKStoreFileName;
        m_ExecItemExecTime 
= DateTime.Now;

        
if (File.Exists(FileName))
            File.Delete(FileName);

        
if (!DoneOk)
        
{
            m_ItemState 
= BKExecItemState.出错;
            ErrMsg 
= Msg;
            SaveToDisk2();
            MakeMail();
        }

    }


    
private void MakeMail()
    
{
        StringBuilder sb 
= new StringBuilder();
        sb.Append(
"提交人:").Append(this.m_Op).Append("<BR>");
        sb.Append(
"提交时间:").Append(this.ExecItemCreateTime).Append("<BR>");
        sb.Append(
"对象:").Append(this.m_ExecItemClass.Name).Append("<BR>");
        sb.Append(
"方法:").Append(this.m_ExecItemMethed).Append("<BR>");
        sb.Append(
"参数:");
        
foreach (object o in this.m_ExecItemParamList)
            sb.Append(o.ToString()).Append(
",");
        sb.Append(
"<BR>");
        sb.Append(
"执行时间:").Append(this.m_ExecItemExecTime).Append("<BR>");
        sb.Append(
"错误信息:").Append(this.ErrMsg).Append("<BR>");
        
string mb = sb.ToString();
        
//APP.Mail.Send(m_Op + ":" + m_ExecItemClass.Name + "后台处理错", mb, "", BkExecManager.BkManager, "");
    }

}

具体调用方法为 

1 ,首先新调一个后台任务对象. 
2 ,将之加入到任务队列中. 

ExecItem ei 
=   new  ExecItem( typeof (CacheManager),
    
" RefreshObject " ,
    
new   object []  { Objtype, Params, ct } ,
    
" 缓存刷新 " ,
    
"" ,
    
false );   // 注意以后可以设置为false,即刷新任务不保存到磁盘,以免影响磁盘性能.

BkExecManager.Execer.AddBkExecItem(ei);

http://www.niftyadmin.cn/n/1412640.html

相关文章

python 字典元素操作

#字典创建>>> dict2 { abc: 123, 98.6: 37 }>>> dict2[98.6]37>>> dict2["abc"]123 键必须不可变&#xff0c;所以可以用数字&#xff0c;字符串或元组充当&#xff0c;用列表就不行#!/usr/bin/pythondict {[Name]: Zara, Age: 7} prin…

ssh 长时间断开连接

2019独角兽企业重金招聘Python工程师标准>>> [roothost-172-16-5-10 ~]# packet_write_wait: Connection to 192.168.0.157 port 22: Broken pipe rootlaptop:/opt//src# iwlist wlan- scan wlan- Interface doesnt support scanning.转载于:https://my.oschina…

使用ASP.NET的GridView导出/儲存資料至Excel,Word,Txt檔,Powerpoint

ps.註解的部分屬於儲存檔案的程式碼 excel.aspx <% Page Language"C#" AutoEventWireup"true" CodeFile"excel.aspx.cs" Inherits"excel" %> 02 03 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q…

操作系统第五章:1、I/O管理

I/O控制方式 缓冲技术 &#xff08;1&#xff09;单缓冲 &#xff08;2&#xff09;双缓冲 &#xff08;3&#xff09;环形缓冲 I/O性能问题 同步&#xff1a;执行一个操作之后&#xff0c;进程触发IO操作并等待(也就是我们说的阻塞)或者轮询的去查看IO操作(也就是我们说…

网页中添加播放器播放视频文件与网页增加背景音乐示例

一.在网页中播放视频文件&#xff0c;以下代码是播放器&#xff0c;再加入如【☆☆动作-欧美-虎胆龙威4-原创02.dvd.rm】电影&#xff0c;打开即可播放了&#xff01; <html><head><title>无标题文档</title><meta http-equiv"Content-Type&qu…

ubuntu不能正常使用make menuconfig的解决方案

so easy sudo apt-get install build-essentialsudo apt-get install libncurses5sudo apt-get install libncurses5-dev happy当然有的时候在执行以上命令的时候会出错&#xff0c;提示要更新“软件列表”&#xff0c;OK&#xff0c;乖乖的先更新再执行以上命令吧。更新命令 s…

day56-1 select的问题以及epoll的使用

select的问题 当进程被唤醒时&#xff0c;不清楚到底哪个socket有数据&#xff0c;只能遍历一遍每一次select的执行&#xff0c;都需要将这进程&#xff0c;再加入到等待队列中为了重复添加等待队列&#xff0c;当每一次操作完成时&#xff0c;也需要从等待队列中删除进程所以s…

操作系统第五章:2、磁盘管理

基本概念 对于磁盘&#xff0c;每个磁道的扇区数并不是常量。绝大多数磁盘都有一些缺陷扇区&#xff0c;因此映射必须用磁盘上的其他空闲扇区来替代这些缺陷扇区。 磁盘缺陷 &#xff30;表&#xff1a;又称为永久缺陷列表&#xff0c;用于记录硬盘生产过程中产生的缺陷。 G表…