|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
来吧!老师们!我代表千千万万的asp.net/C#的初学者在这里呼唤着!server在CSHttpModule.cs文件中的Init办法下有如许一行:
接着在Dispose办法中另有这么一行:
Job?甚么是Job,在CS运转过程当中有甚么用处,又是怎样运转的?这篇专题将叙说Job的事情流程.
你能够这里了解CS中的Job:“干一些琐屑事变的钟点工”。
解说之前要先懂得一个接口:IDisposable,MSDN是如许界说的:界说一种开释分派的非托管资本的办法。当托管工具不再利用时,渣滓接纳器会主动开释分派给该工具的内存,不外,举行渣滓接纳的工夫不成预知。别的,渣滓接纳器对窗口句柄、翻开的文件和流等非托管资本一窍不通。
将此接口的Dispose办法与渣滓接纳器一同利用来显式开释非托管资本。当不再必要工具时,工具的利用者能够挪用此办法。非托管资本(unmanagedresource)?大抵能够如许了解:类实例封装的对不受运转库办理的资本(窗口句柄、数据库毗连等),这些类实例都必需完成IDisposable接口,如:SqlCommand、SqlCeConnection、Timer等。当一个类完成IDisposable时,实例的准确用法是当工具不在必要时挪用Dispose办法删除它,因而,在你完成一个类,而该类又包括其他完成IDisposable的类时,必需挪用Dispose办法。这一般意味着在该类中你必需完成IDisposable。
注:C#言语对Disposable有特别的撑持,你常常会看到以下一段代码:
using(SqlConnectionconnection=newSqlConnection(connectionString))
{
dosomething
}
这里的using就是对IDisposable接口的撑持来完成工具扫除。
言回正传,上面翻开CommunityServerComponents项目中Configuration文件夹中的Job.cs:
publicclassJob:IDisposable
{
代码太长…
}
本来Job是完成了IDisposable的类,有了下面对IDisposable的注释不难了解,因为Job中挪用了Timer,而Timer又是完成了IDisposable的类,Job类完成接口IDisposable是为了开释利用的Timer,即挪用Timer中的Dispose()。看看以下的代码能够证明这一点:
publicvoidDispose()
{
if(_timer!=null&&!disposed)
{
lock(this)
{
_timer.Dispose();
_timer=null;
disposed=true;
}
}
}
另有需要对Timer类做一些复杂的先容:Timer是供应以指定的工夫距离实行办法的机制,说白了就是一个准时器。Timer可使用TimerCallback托付指定但愿Timer工夫抵达时实行的办法。也就是说,假如准时器的工夫抵达了,将实行TimerCallback托付指向的办法。
(注:创立计时器时,能够指定在第一次实行办法之前守候的工夫量(停止工夫)和今后的实行时代守候的工夫量(工夫周期)。可使用Change办法变动这些值或禁用计时器。)
我们看一下代码:
privateTimer_timer=null;
publicvoidInitializeTimer(Guidid)
{
if(_timer==null&&Enabled)
{
_timer=newTimer(newTimerCallback(timer_Callback),id,Interval,Interval);
}
}
privatevoidtimer_Callback(objectstate)
{
Guidid=(Guid)state;
if(id!=Jobs.Instance().CurrentID)
{
this.Dispose();
return;
}
if(!Enabled)
return;
_timer.Change(Timeout.Infinite,Timeout.Infinite);
ExecuteJob();
if(Enabled)
_timer.Change(Interval,Interval);
else
this.Dispose();
}
经由过程_timer=newTimer(newTimerCallback(timer_Callback),id,Interval,Interval);
先实例化了一个准时器,并制订了该准时器触发时分挪用的办法是timer_Callback。
(前一个Interval指:
后一个Interval指:
)
在回调办法timer_Callback只需挪用的是ExecuteJob()办法,该办法经由过程挪用Job类的Jobs类中传送过去得xml节点信息,利用反射实例化一个具有IJob接口的类(IJob接口请求完成它的类都具有Execute办法),而且实行类中的Execute办法。我们剖析一个完成了IJob的类,翻开Components文件夹下的EmailJob.cs,该类中只要一个办法,就是Execute,该办法又挪用Emails.cs下的SendQueuedEmails办法,次要用处是发送数据库行列中的Email(这里Email来历于用户注册时必要发送的注册乐成的信息等等,一般的做法是在用户注册终了后即刻就发送Email,而CS接纳的是将要发送的Email存进数据库,在必定的距离工夫后一致处置这段工夫内的一切Email发送,处置的类就是EmailJob.cs)。这里还要注重一点:TimerCallback的实例不在创立计时器的线程中实行,而是在体系供应的一个独自线程池线程中实行。
再来看看CommunityServerComponents项面前目今的Jobs.cs文件,这个类第一次看计划的有点糟糕,它的机关函数是静态的,可是在静态的机关函数中实例化它本人,实例化后保留在staticreadonly的变量里(晕了吧,嘿嘿!)实在这叫单件形式(Singleton形式),确保全局中有且只要一个Jobs实例。Jobs的实例次要完成从CS的设置文件中读掏出每一个Job的设置信息,先看一下Job的设置信息:
<Jobsminutes="5"singleThread="false">
<jobname="SiteStatisticsUpdates"type="CommunityServer.Components.SiteStatisticsJob,CommunityServer.Components"enabled="true"enableShutDown="false"/>
<jobname="ForumsIndexing"type="CommunityServer.Discussions.Components.ForumsSearchJob,CommunityServer.Discussions"enabled="false"enableShutDown="false"/>
<jobname="WeblogIndexing"type="CommunityServer.Blogs.Components.WeblogSearchJob,CommunityServer.Blogs"enabled="false"enableShutDown="false"/>
<jobname="GalleryIndexing"type="CommunityServer.Galleries.Components.GallerySearchJob,CommunityServer.Galleries"enabled="false"enableShutDown="false"/>
<jobname="AnonymousUsers"minutes="1"type="CommunityServer.Components.AnonymousUserJob,CommunityServer.Components"enabled="true"enableShutDown="false"/>
<jobsingleThread="false"minutes="5"name="Emails"type="CommunityServer.Components.EmailJob,CommunityServer.Components"enabled="true"enableShutDown="false"failureInterval="1"numberOfTries="10"/>
<jobname="Referrals"type="CommunityServer.Components.ReferralsJob,CommunityServer.Components"enabled="true"enableShutDown="false"/>
<jobname="Views"type="CommunityServer.Components.ViewsJob,CommunityServer.Components"enabled="true"enableShutDown="false"/>
<jobname="RecentBlogContent"type="CommunityServer.Blogs.Components.RecentContentJob,CommunityServer.Blogs"enabled="true"enableShutDown="false"/>
<jobname="RebuildThumbnailsJob"type="CommunityServer.Galleries.Components.RebuildThumbnailsJob,CommunityServer.Galleries"picturesPerRun="25"enabled="true"enableShutDown="false"/>
</Jobs>
注释一下这些xml的节点意义:
<Jobsminutes="5"singleThread="false">
minutes:实行回调函数TimerCallback的工夫与工夫距离,这里是5分钟,也就是说实行回调函数在初始化哀求以后的五分钟入手下手,而且每五分钟一次。
singleThread:是单线程仍是多线程,后面说过为Timer创立的TimerCallback的实例不在创立计时器的线程中实行,而是在体系供应的一个独自线程池线程中实行,假如值为“false”就会为每一个Job创立一个Timer线程,假如为“true”就创立一个Timer。
<job>节点对照天真,一些属性是该节点独有的,这是依据完成IJob接口类的必要决意的,以Email发送的类为例:
<jobsingleThread="false"minutes="5"name="Emails"type="CommunityServer.Components.EmailJob,CommunityServer.Components"enabled="true"enableShutDown="false"failureInterval="1"numberOfTries="10"/>
singleThread:当头CS版本中没有效到。
Minutes:实行回调函数TimerCallback的工夫与工夫距离,这里是5分钟。
name:该Job的独一标识。
type:该Job地点的名字空间,逗号前面的是该Job地点的程序集dll文件称号。
enabled:假如为“false”该Job会被封闭,也就是不会实例化一个准时器。“true”则为开启该Job。
enableShutDown:这个有点意义,用处是当该Job在实行Execute时,假如永生非常是不是封闭这个Job,也就是说是不是还同意它再次运转。“false”暗示同意,“true”暗示不同意。
failureInterval:假如发送邮件失利,与下次实验再次发送的工夫距离,单元是分钟。
numberOfTries:假如发送邮件失利,该Job会实验几回,这里是10次。
如今回到我们入手下手时分在CSHttpModule.cs中看到的这句:
Jobs.Instance().Start();
起首挪用Jobs,实例化一个Jobs类,这个类在CS中有且只要一个实例。以后挪用Jobs中的Start()办法。Jobs为了确保体系的平安,在入手下手之前先挪用Stop(),现开释之前为Job实例化的非托管资本(实在就是挪用Timer与Job上面的Dispose办法,这也是为何Job要完成IDispose接口的缘故原由,是想一下,假如前一次界说的准时器没有被开释,然后又接实在例化一个,然后如许多反复几回...哈哈,你的CS就会有N个线程在跑,服务器很快就会挂失落的)。
开释完资本后(不管有无CS城市这么做),接着就会实例化每一个完成了IJob的类,依据上述的设置文件界说一个Timer大概让每一个Job都界说一个本人的Timer(这就相称于给钟点工一致一个事情工夫大概给每一个钟点工都划定一个事情工夫,划定完后该干甚么的就干往吧,只需工夫到了就得干活)。再往下,就本人剖析吧,也就没有甚么困难了…
不晓得为何我的团队中的几个成员总是不克不及了解这个实行历程,我注释了半天,最初发明了成绩:
回到CSHttpModule.cs文件中来,这是一个完成了IHttpModule接口的类,完成该接口的类都要有一个Init办法,我们看到,一切的Job入手下手初始化的出发点也是从这个办法中挪用的。可是我的小构成员都以为每一个Http哀求城市挪用一次Init办法,
publicvoidInit(HttpApplicationapplication)
{
//Wire-upapplicationevents
//
application.BeginRequest+=newEventHandler(this.Application_BeginRequest);
application.AuthenticateRequest+=newEventHandler(Application_AuthenticateRequest);
application.Error+=newEventHandler(this.Application_OnError);
application.AuthorizeRequest+=newEventHandler(this.Application_AuthorizeRequest);
//settingsID=SiteSettingsManager.GetSiteSettings(application.Context).SettingsID;
Jobs.Instance().Start();
//CSExceptionex=newCSException(CSExceptionType.ApplicationStart,"AppicationStarted"+AppDomain.CurrentDomain.FriendlyName);
//ex.Log();
}
也就是说每一个哀求都实例化一个CSHttpModule,假如是如许Init办法就会屡次被挪用,那末假如有1000个Http哀求Jobs就会Start1000次,这原本就剖析欠亨。
实在以为CSHttpModule会被实例化屡次就是一个很年夜的毛病,在全部CS运转过程当中只会实例化一个CSHttpModule类,也就是说Init只会被实行一次。
有理由相信是能提供更出色的性能。很多平台无法支持复杂的编译器,因此需要二次编译来减少本地编译器的复杂度。当然可能做不到java编译器那么简易。 |
|