国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

Community Server專題七: Job & Timer

2024-07-21 02:29:27
字體:
供稿:網(wǎng)友
中國最大的web開發(fā)資源網(wǎng)站及技術(shù)社區(qū),

在cshttpmodule.cs文件中的init方法下有這樣一行:

接著在dispose方法中還有這么一行:

job?什么是job,在cs運(yùn)行過程中有什么用途,又是如何運(yùn)行的?這篇專題將敘述job的工作流程.

你可以這里理解cs中的job:“干一些零碎事情的鐘點(diǎn)工”。

講解之前要先了解一個(gè)接口:idisposable,msdn是這樣定義的:定義一種釋放分配的非托管資源的方法。當(dāng)托管對象不再使用時(shí),垃圾回收器會(huì)自動(dòng)釋放分配給該對象的內(nèi)存,不過,進(jìn)行垃圾回收的時(shí)間不可預(yù)知。另外,垃圾回收器對窗口句柄、打開的文件和流等非托管資源一無所知。

將此接口的 dispose 方法與垃圾回收器一起使用來顯式釋放非托管資源。當(dāng)不再需要對象時(shí),對象的使用者可以調(diào)用此方法。非托管資源(unmanaged resource)?大致可以這樣理解:類實(shí)例封裝的對不受運(yùn)行庫管理的資源(窗口句柄、數(shù)據(jù)庫連接等),這些類實(shí)例都必須實(shí)現(xiàn)idisposable接口,如:sqlcommand 、sqlceconnection、timer等。當(dāng)一個(gè)類實(shí)現(xiàn)idisposable時(shí),實(shí)例的正確用法是當(dāng)對象不在需要時(shí)調(diào)用dispose方法刪除它,因此,在你實(shí)現(xiàn)一個(gè)類,而該類又包含其他實(shí)現(xiàn)idisposable的類時(shí),必須調(diào)用dispose方法。這通常意味著在該類中你必須實(shí)現(xiàn)idisposable。

注:c#語言對disposable有特殊的支持,你經(jīng)常會(huì)看到如下一段代碼:


using(sqlconnection connection = new sqlconnection(connectionstring))

{

    //do something

}

這里的using就是對idisposable接口的支持來實(shí)現(xiàn)對象清除。

言歸正傳,下面打開communityservercomponents項(xiàng)目中configuration文件夾中的job.cs:

public class job : idisposable

{

//代碼太長…

}

原來job是實(shí)現(xiàn)了idisposable的類,有了上面對idisposable的解釋不難理解,由于job中調(diào)用了timer,而timer又是實(shí)現(xiàn)了idisposable的類,job類實(shí)現(xiàn)接口idisposable是為了釋放使用的timer,即調(diào)用timer中的dispose()??纯匆韵碌拇a可以證實(shí)這一點(diǎn):

public void dispose()

{

    if(_timer!= null && !disposed)

    {

        lock(this)

        {

            _timer.dispose();

            _timer = null;

            disposed = true;

        }

    }

}

還有必要對timer類做一些簡單的介紹:timer是提供以指定的時(shí)間間隔執(zhí)行方法的機(jī)制,說白了就是一個(gè)定時(shí)器。timer可以使用 timercallback 委托指定希望 timer時(shí)間到達(dá)時(shí)執(zhí)行的方法。也就是說,如果定時(shí)器的時(shí)間到達(dá)了,將執(zhí)行timercallback 委托指向的方法。

(注:創(chuàng)建計(jì)時(shí)器時(shí),可以指定在第一次執(zhí)行方法之前等待的時(shí)間量(截止時(shí)間)以及此后的執(zhí)行期間等待的時(shí)間量(時(shí)間周期)??梢允褂?change 方法更改這些值或禁用計(jì)時(shí)器。)

我們看一下代碼:

private timer _timer = null;

public void initializetimer(guid id)

{

     if(_timer == null && enabled)

     {

         _timer = new timer(new timercallback(timer_callback), id,interval, interval);

     }

}

private void timer_callback(object state)

{

    guid id = (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 = new timer(new timercallback(timer_callback), id,interval, interval);

先實(shí)例化了一個(gè)定時(shí)器,并制定了該定時(shí)器觸發(fā)時(shí)候調(diào)用的方法是timer_callback。

(前一個(gè)interval指:

后一個(gè)interval指:

)

在回調(diào)方法timer_callback只要調(diào)用的是executejob()方法,該方法通過調(diào)用job類的jobs類中傳遞過來得xml節(jié)點(diǎn)信息,使用反射實(shí)例化一個(gè)具有ijob接口的類(ijob接口要求實(shí)現(xiàn)它的類都具有execute方法),并且執(zhí)行類中的execute方法。我們分析一個(gè)實(shí)現(xiàn)了ijob的類,打開components文件夾下的emailjob.cs,該類中只有一個(gè)方法,就是execute,該方法又調(diào)用emails.cs下的sendqueuedemails方法,主要用途是發(fā)送數(shù)據(jù)庫隊(duì)列中的email(這里email來源于用戶注冊時(shí)需要發(fā)送的注冊成功的信息等等,通常的做法是在用戶注冊完畢后馬上就發(fā)送email,而cs采用的是將要發(fā)送的email存入數(shù)據(jù)庫,在一定的間隔時(shí)間后統(tǒng)一處理這段時(shí)間內(nèi)的所有email發(fā)送,處理的類就是emailjob.cs)。這里還要注意一點(diǎn):timercallback的實(shí)例不在創(chuàng)建計(jì)時(shí)器的線程中執(zhí)行,而是在系統(tǒng)提供的一個(gè)單獨(dú)線程池線程中執(zhí)行。

再來看看communityservercomponents項(xiàng)目下的jobs.cs文件,這個(gè)類第一次看設(shè)計(jì)的有點(diǎn)蹩腳,它的構(gòu)造函數(shù)是靜態(tài)的,但是在靜態(tài)的構(gòu)造函數(shù)中實(shí)例化它自己,實(shí)例化后保存在static readonly的變量里(暈了吧,嘿嘿!)其實(shí)這叫單件模式(singleton模式),確保全局中有且只有一個(gè)jobs實(shí)例。jobs的實(shí)例主要完成從cs的配置文件中讀取出每個(gè)job的配置信息,先看一下job的配置信息:

<jobs minutes = "5" singlethread = "false">

         <job name = "sitestatisticsupdates" type = "communityserver.components.sitestatisticsjob, communityserver.components" enabled = "true" enableshutdown = "false" />

         <job name = "forumsindexing" type = "communityserver.discussions.components.forumssearchjob, communityserver.discussions" enabled = "false" enableshutdown = "false" />

         <job name = "weblogindexing" type = "communityserver.blogs.components.weblogsearchjob, communityserver.blogs" enabled = "false" enableshutdown = "false" />

         <job name = "galleryindexing" type = "communityserver.galleries.components.gallerysearchjob, communityserver.galleries" enabled = "false" enableshutdown = "false" />

         <job name = "anonymoususers" minutes = "1" type = "communityserver.components.anonymoususerjob, communityserver.components" enabled = "true" enableshutdown = "false" />

         <job singlethread = "false" minutes = "5" name = "emails" type = "communityserver.components.emailjob, communityserver.components" enabled = "true" enableshutdown = "false" failureinterval = "1" numberoftries = "10" />

         <job name = "referrals" type = "communityserver.components.referralsjob, communityserver.components" enabled = "true" enableshutdown = "false" />

         <job name = "views" type = "communityserver.components.viewsjob, communityserver.components" enabled = "true" enableshutdown = "false" />

         <job name = "recentblogcontent" type = "communityserver.blogs.components.recentcontentjob, communityserver.blogs" enabled = "true" enableshutdown = "false" />

         <job name = "rebuildthumbnailsjob" type = "communityserver.galleries.components.rebuildthumbnailsjob, communityserver.galleries" picturesperrun = "25" enabled = "true" enableshutdown = "false" />

</jobs>

解釋一下這些xml的節(jié)點(diǎn)意思:

<jobs minutes = "5" singlethread = "false">

minutes:執(zhí)行回調(diào)函數(shù)timercallback的時(shí)間與時(shí)間間隔,這里是5分鐘,也就是說執(zhí)行回調(diào)函數(shù)在初始化請求之后的五分鐘開始,并且每五分鐘一次。

singlethread:是單線程還是多線程,前面說過為timer創(chuàng)建的timercallback的實(shí)例不在創(chuàng)建計(jì)時(shí)器的線程中執(zhí)行,而是在系統(tǒng)提供的一個(gè)單獨(dú)線程池線程中執(zhí)行,如果值為“false”就會(huì)為每個(gè)job創(chuàng)建一個(gè)timer線程,如果為“true”就創(chuàng)建一個(gè)timer。

<job>節(jié)點(diǎn)比較靈活,一些屬性是該節(jié)點(diǎn)特有的,這是根據(jù)實(shí)現(xiàn)ijob接口類的需要決定的,以email發(fā)送的類為例:


<job singlethread = "false" minutes = "5" name = "emails" type = "communityserver.components.emailjob, communityserver.components" enabled = "true" enableshutdown = "false" failureinterval = "1" numberoftries = "10" />


singlethread:當(dāng)頭cs版本中沒有用到。

minutes:執(zhí)行回調(diào)函數(shù)timercallback的時(shí)間與時(shí)間間隔,這里是5分鐘。

name:該job的唯一標(biāo)識(shí)。

type:該job所在的名字空間,逗號(hào)后面的是該job所在的程序集dll文件名稱。

enabled:如果為“false”該job會(huì)被關(guān)閉,也就是不會(huì)實(shí)例化一個(gè)定時(shí)器?!皌rue”則為開啟該job。

enableshutdown:這個(gè)有點(diǎn)意思,用途是當(dāng)該job在執(zhí)行execute時(shí),如果長生異常是否關(guān)閉這個(gè)job,也就是說是否還允許它再次運(yùn)行?!癴alse”表示允許,“true”表示不允許。

failureinterval:如果發(fā)送郵件失敗,與下次嘗試再次發(fā)送的時(shí)間間隔,單位是分鐘。

numberoftries:如果發(fā)送郵件失敗,該job會(huì)嘗試幾次,這里是10次。

   現(xiàn)在回到我們開始時(shí)候在cshttpmodule.cs中看到的這句:

jobs.instance().start();

首先調(diào)用jobs,實(shí)例化一個(gè)jobs類,這個(gè)類在cs中有且只有一個(gè)實(shí)例。之后調(diào)用jobs中的start()方法。jobs為了確保系統(tǒng)的安全,在開始之前先調(diào)用stop(),現(xiàn)釋放之前為job實(shí)例化的非托管資源(其實(shí)就是調(diào)用timer與job下面的dispose方法,這也是為什么job要實(shí)現(xiàn)idispose接口的原因,是想一下,如果前一次定義的定時(shí)器沒有被釋放,然后又接著實(shí)例化一個(gè),然后這樣多重復(fù)幾次...哈哈,你的cs就會(huì)有n個(gè)線程在跑,服務(wù)器很快就會(huì)掛掉的)。

釋放完資源后(無論有沒有cs都會(huì)這么做),接著就會(huì)實(shí)例化每個(gè)實(shí)現(xiàn)了ijob的類,根據(jù)上述的配置文件定義一個(gè)timer或者讓每個(gè)job都定義一個(gè)自己的timer(這就相當(dāng)于給鐘點(diǎn)工統(tǒng)一一個(gè)工作時(shí)間或者給每個(gè)鐘點(diǎn)工都規(guī)定一個(gè)工作時(shí)間,規(guī)定完后該干什么的就干去吧,只要時(shí)間到了就得干活)。再往下,就自己分析吧,也就沒有什么難題了…

不知道為什么我的團(tuán)隊(duì)中的幾個(gè)成員老是不能理解這個(gè)執(zhí)行過程,我解釋了半天,最后發(fā)現(xiàn)了問題:

回到cshttpmodule.cs文件中來,這是一個(gè)實(shí)現(xiàn)了ihttpmodule接口的類,實(shí)現(xiàn)該接口的類都要有一個(gè)init方法,我們看到,所有的job開始初始化的起點(diǎn)也是從這個(gè)方法中調(diào)用的。但是我的小組成員都認(rèn)為每個(gè)http請求都會(huì)調(diào)用一次init方法,

public void init(httpapplication application)

{

    // wire-up application events

    //

    application.beginrequest += new eventhandler(this.application_beginrequest);

    application.authenticaterequest += new eventhandler(application_authenticaterequest);

    application.error += new eventhandler(this.application_onerror);

    application.authorizerequest += new eventhandler(this.application_authorizerequest);

   

    //settingsid = sitesettingsmanager.getsitesettings(application.context).settingsid;

    jobs.instance().start();

    //csexception ex = new csexception(csexceptiontype.applicationstart, "appication started " +  appdomain.currentdomain.friendlyname);

    //ex.log();

}

也就是說每個(gè)請求都實(shí)例化一個(gè)cshttpmodule,如果是這樣init方法就會(huì)多次被調(diào)用,那么如果有1000個(gè)http請求jobs就會(huì)start 1000次,這本來就分析不通。

其實(shí)認(rèn)為cshttpmodule會(huì)被實(shí)例化多次就是一個(gè)很大的錯(cuò)誤,在整個(gè)cs運(yùn)行過程中只會(huì)實(shí)例化一個(gè)cshttpmodule類,也就是說init只會(huì)被執(zhí)行一次。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武义县| 隆昌县| 栾川县| 油尖旺区| 石城县| 宾川县| 阜城县| 都兰县| 出国| 盐津县| 阿巴嘎旗| 应城市| 荃湾区| 襄汾县| 平泉县| 武冈市| 孙吴县| 夏津县| 武功县| 永顺县| 太保市| 徐闻县| 南郑县| 五莲县| 双柏县| 台东市| 左云县| 孟连| 武邑县| 玛多县| 昌都县| 灵宝市| 玉龙| 岳阳县| 彭水| 肇源县| 沂源县| 麻江县| 泸溪县| 甘南县| 怀宁县|