海妖 发表于 2015-1-18 11:26:11

ASP.NET网站制作之简化异步操纵(下)──构建AsyncTaskDispatcher简化多个异步操纵之间的合作挪用仓酷 ...

那做企业软件是不是最好用J2EE?媒介

在《简化异步操纵(上):利用CCR和AsyncEnumerator简化异步操纵》一文中,我们谈到了异步编程的主要性,利用异步操纵的难点,和怎样利用CCR和AsyncEnumerator来简化异步操纵的挪用。有了这些组件的辅助,异步操纵也能够真正利用传统的开辟体例来编写了——这意味着各类缺点,比方没法在“仓库”中保留一时变量,没法try…catch…finally和using等成绩都不复存在了。这些组件让异步编程一会儿优美了很多。
不外,现有的帮助还不敷以面临一些庞大的场景。比方,要使多个有依附的异步操纵尽量的“并行”,我们还必要构建分外的办理计划。在这片文章里,我们将编写一个AsyncTaskDispatcher来简化此类场景下的开辟。天然,您也能够下载它的代码后加以修正,使它能更进一步满意您的需求。
AsyncTaskDispatcher的计划与完成

AsyncTaskDispatcher的方针是为了简化多个异步操纵之间的和谐挪用,使得各别步操纵之间可以尽量的“并行化”。在我的假想中,AsyncTaskDispatcher应当如许利用:

[*]起首创立一个AsyncTaskDispatcher对象。
[*]在AsyncTaskDispatcher对象中注册各类异步义务,同时指定各义务之间的依附干系。
[*]利用AsyncTaskDispatcher对象的BeginDispatch和EndDispath办法构成了一个APM形式,把一切异步义务作为一个全体来挪用。
[*]假如任何一个异步义务抛出非常:

[*]AsyncTaskDispatcher中断分拨,并作废正在实行的义务,全部异步伐用当即完成。
[*]AsyncTaskDispatcher中断分拨,并守候正在实行的义务完成后全部异步伐用才算停止。

在经由了思索和对照以后,终极我选择基于AsyncEnumerator机关AsyncTaskDispatcher,由于:


[*]AsyncEnumerator久经测试,可让我把注重力会合在分派异步义务的逻辑上,而不必要过渡存眷异步操纵中的各类八怪七喇的成绩。
[*]AsyncEnumerator的利用模子包管了一点:除异步操纵自己以外,其他的逻辑都可使用串行的体例来实行。如许进一步制止了多线程情况下的各类成绩,特别是在把持各类形态的时分这点更加主要(固然CCR也有这个特性)。
[*]AsyncEnumerator个头玲珑,仅数十K巨细,假如基于CCR开辟,则必要一个几兆的再分发包(redistributionpackage)。
[*]AsyncEnumerator自带了BeginExecute和EndExecute办法构成的APM形式,能够间接利用
[*]AsyncEnumerator已包括内置的“作废”功效。
[*]AsyncEnumerator已内置SynchronizationContext,可以在WinForm或WPF界面中间接利用。
那末我们就入手下手AsyncTaskDispatcher的完成。起首我们要断定一个异步义务包括哪些信息。的是“那些工具组成了一个异步义务”,大概说,“机关一个异步义务必要哪些信息”。AsyncTask的界说以下:
publicclassAsyncTask{privateAsyncTask[]m_dependencies;privateHashSet<AsyncTask>m_successors;publicobjectId{get;privateset;}publicobjectContext{get;privateset;}publicAsyncTaskStatusStatus{get;internalset;}internalFunc<object,DispatchPolicy>Predicate{get;privateset;}internalFunc<AsyncCallback,object,object,IAsyncResult>Begin{get;privateset;}internalAction<IAsyncResult,bool,object>End{get;privateset;}privateAsyncTask(){}internalAsyncTask(objectid,Func<object,DispatchPolicy>predicate,Func<AsyncCallback,object,object,IAsyncResult>begin,Action<IAsyncResult,bool,object>end,objectcontext,IEnumerable<AsyncTask>dependencies){this.Id=id;this.Predicate=predicate;this.Begin=begin;this.End=end;this.Context=context;this.Status=AsyncTaskStatus.Pending;this.m_successors=newHashSet<AsyncTask>();this.m_dependencies=dependencies.Where(d=>d!=null).Distinct().ToArray();foreach(vartaskinthis.m_dependencies){task.m_successors.Add(this);}}internalIEnumerable<AsyncTask>Successors{get{returnthis.m_successors;}}internalboolDependenciesSucceeded{get{returnthis.m_dependencies.All(d=>d.Status==AsyncTaskStatus.Succeeded||d.Status==AsyncTaskStatus.MarkedAsSucceeded);}}internalvoidClose(){this.Predicate=null;this.Begin=null;this.End=null;this.m_dependencies=null;this.m_successors=null;}internalAsyncTaskMakeSnapshot(){returnnewAsyncTask{Id=this.Id,Status=this.Status};}}以下是机关AsyncTask对象时必要供应的信息:


[*]id:一个object范例对象,用于标识一个异步义务,在统一个AsyncTaskDispatcher中独一。
[*]context:一个object范例的高低文对象,它是注册异步义务时供应的恣意对象,AsyncTaskDispatcher会在其他操纵中供应该对象。
[*]predicate:一个Func
[*]begin:一个Func
[*]end:一个Action
[*]dependencies:以后义务所依附的其他异步义务
别的,另有一些成员用于帮助开辟:


[*]Status属性:标明该异步义务的形态,它们是:

[*]MarkedAsSucceeded:暗示该义务在predicate托付实行时被标志为“乐成”
[*]Succeeded:暗示该义务一般运转乐成
[*]Failed:暗示该义务实行失利
[*]Pending:暗示该义务还处于守候形态
[*]MarkedAsCancelled:暗示该义务在predicate托付实行时被标志为“作废”
[*]Cancelling:标明该义务已倡议,但由于其他义务的失利正处于作废阶段,守候停止。
[*]Cancelled:标明该义务已倡议,但由于其他义务的失利而被作废。
[*]Executing:标明该义务正在实行

[*]Successors属性:该义务的一切后继异步义务
[*]DependenciesSucceeded属性:暗示该义务所依附的异步义务是不是全体乐成
[*]Close办法:扫除该义务中一切非公然数据,使它们在AsyncTask被内部援用的情形下也能尽早接纳
[*]MakeSnapshot办法:前往暗示以后AsyncTask对象形态的快照对象
AsyncTask的年夜部分红员十分简单了解。只要一点值得一提,就是在某个异步义务实行失利的情形下AsyncTaskDispatcher的举动怎样。我完成的AsyncTaskDispatcher在机关时能够承受一个参数cancelOnFailure,标明某个义务堕落以后是当即停止全部分拨历程(cancelOnFailure为true),仍是必要守候正在运转的义务完成(cancelOnFailure为false)。
publicclassAsyncTaskDispatcher{privateDictionary<object,AsyncTask>m_tasks;publicboolCancelOnFailure{get;privateset;}publicDispatchStatusStatus{get;privateset;}...publicAsyncTaskDispatcher():this(false){}publicAsyncTaskDispatcher(boolcancelOnFailure){this.CancelOnFailure=cancelOnFailure;this.m_tasks=newDictionary<object,AsyncTask>();this.Status=DispatchStatus.NotStarted;}...}假如cancelOnFailure为true,作为一个全体的异步分拨操纵在碰到毛病时会当即完成,内部逻辑即可持续实行下往。可是关于那些已入手下手的异步义务,它们的End托付在接上去的某一时候仍旧会被挪用,不然便可能会形成资本保守。一个异步义务的End托付能够经由过程它的cancelling参数来判别以后挪用是一个一般的停止,仍是一个作废历程。假如cancelling为true,则申明全部分拨历程已停止,而个中某个异步义务呈现毛病;假如cancelling为false,则标明全部分拨历程还在举行,以后异步义务一般停止——可是这其实不暗示此时全体分拨过程当中没有呈现成绩,有大概某个异步义务已堕落,可是因为cancelOnFailure为false,AsyncTaskDispatcher正在守候其他异步义务(也包含以后义务)的“一般停止”。
在AsyncTaskDispatcher中,我们将保护一个字典,以便经由过程id来查找一个AsyncTask对象。开辟职员能够经由过程RegisterTask办法来创立一个AsyncTask对象:
publicAsyncTaskRegisterTask(objectid,Func<object,DispatchPolicy>predicate,Func<AsyncCallback,object,object,IAsyncResult>begin,Action<IAsyncResult,bool,object>end,objectcontext,paramsobject[]dependencies){lock(this.m_tasks){if(this.Status!=DispatchStatus.NotStarted){thrownewInvalidOperationException("Taskcanonlyberegisteredbeforedispatching.");}this.CheckRegisterTaskArgs(id,begin,end,dependencies);AsyncTasktask=newAsyncTask(id,predicate,begin,end,context,dependencies.Select(d=>this.m_tasks));this.m_tasks.Add(id,task);returntask;}}AsyncTaskDispatcher在各办法外部利用了lock,这是种十分大略的锁举动——固然确保了它在多线程情况下也能坚持形态的一致,可是其功能却比一丝不苟的锁把持要差一些。不外这究竟不是今朝的关头,更况且必要在多线程情况下利用AsyncTaskDispatcher的场景少之又少。RegisterTask办法有多个重载,它们都将挪用间接发送给下面的RegisterTask完成。这个办法会依据传进的依附id找出新义务所依附的异步义务,机关一个AsyncTask对象,并将其放进字典中。
为了构成一个尺度的APM形式,AsyncTaskDispatcher供应了BeginDispatch和EndDispatch办法:
privateDictionay<object,Exception>m_taskExceptions;publicIAsyncResultBeginDispatch(AsyncCallbackasyncCallback,objectasyncState){lock(this.m_tasks){if(this.Status!=DispatchStatus.NotStarted){thrownewInvalidOperationException("AnAsyncTaskDispatchercanbestartedonlyonce.");}this.Status=DispatchStatus.Dispatching;}this.m_taskExceptions=newDictionay<object,Exception>();vartaskToStart=this.m_tasks.Values.Where(t=>t.DependenciesSucceeded).ToList();IEnumerator<int>enumerator=this.GetWorkerEnumerator(taskToStart);this.m_asyncEnumerator=newAsyncEnumerator();returnthis.m_asyncEnumerator.BeginExecute(enumerator,asyncCallback,asyncState);}publicvoidEndDispatch(IAsyncResultasyncResult){this.m_asyncEnumerator.EndExecute(asyncResult);if(this.m_taskExceptions.Count>0){thrownewDispatchException(this.GetTaskSnapshots(),this.m_taskExceptions);}}在BeginDispatch办法中,将会选择出一切不存在依附的义务,它们会被作为首零售起的异步义务。它们会被传进GetWorkerEnumerator办法用于机关一个IEnumerator对象,并将其交给AsyncEnumerator实行。全部实行过程当中碰到的非常城市被搜集起来,而且在EndDispatch实行中抛出一个包括这些非常信息的DispatchException。异步义务抛出的每一个非常城市利用HandleTaskFailure办法举行处置:
privateboolHandleTaskFailure(AsyncTasktask,Exceptionex){this.m_taskExceptions.Add(task.Id,ex);task.Status=AsyncTaskStatus.Failed;task.Close();if(this.CancelOnFailure){lock(this.m_tasks){varrunningTasks=this.m_tasks.Values.Where(t=>t.Status==AsyncTaskStatus.Executing);foreach(AsyncTasktinrunningTasks){t.Status=AsyncTaskStatus.Cancelling;}}this.Status=DispatchStatus.Cancelling;this.m_asyncEnumerator.Cancel(null);returntrue;}else{this.Status=DispatchStatus.Waiting;returnfalse;}}HandleTaskFailure承受两个参数,一是堕落的AsyncTask对象,二即是被抛出的非常,并前往一个值暗示是不是应当当即中断义务分拨。在搜集了非常信息,设定了义务形态并将其封闭以后。则会依据机关AsyncTaskDispatcher对象时所指定的CancelOnFailure值来断定接上去的举动。假如CancelOnFailure为true(暗示作废正在运转的对象),便将正在实行的异步任务全体标志为Cancelling形态,并挪用AsyncEnumerator的Cancel办法作废正在实行的异步义务。依据CancelOnFailure的分歧,AsyncTaskDispatcher本身形态将会酿成Cancelling(暗示正在作废已分拨的义务,这个形态不会保持久长)或Waiting(暗示正在守候已分拨的义务完成),而HandleTaskFailure办法也会前往对应的了局。
之条件到,假如一个异步义务的End托付对象被实行时,其cancelling参数为false,其实不能申明其他义务没有碰到任何毛病。不外从这段完成中即可得知,开辟职员只需共同AsyncTaskDispatcher的形态即可确认更多细节:假如此时AsyncTaskDispatcher的形态为Waiting,则暗示之前已有义务失利了。
publicIEnumerator<int>GetWorkerEnumerator(IEnumerable<AsyncTask>tasksToStart){this.m_runningTaskCount=0;foreach(AsyncTasktaskintasksToStart){try{this.Start(task);}catch(AsyncTaskExceptionex){if(this.HandleTaskFailure(ex.Task,ex.InnerException)){this.Status=DispatchStatus.Finished;yieldbreak;}break;}}...}以上代码片段为GetWorkerEnumerator办法的一部分,用于启动首批被分拨的异步义务。我们将遍历每一个异步义务,并挪用Start办法将其启动。Start办法大概会抛出一个范例为AsyncTaskException的外部非常,这个非常不合错误外开释,它的感化仅仅是为了办法间的“通讯”——“非常”切实其实是用来暗示毛病的一种优异体例,它可以容易地从逻辑中跳出,而且在符合的中央举行处置。在捕捉AsyncTaskException非常以后,就会挪用之前的HandleTaskFailure办法举行处置,假如它前往true(暗示必要当即停止分拨)则利用yiledbreak来跳出GetWorkerEnumerator办法,不然便利用break来跳出轮回——仅仅是跳出轮回而并不是全部GetWorkerEnumerator办法,由于此时其实不请求全部分拨当即停止,接上去的代码将会守候某个已倡议的义务完成,并举行处置:
publicIEnumerator<int>GetWorkerEnumerator(IEnumerable<AsyncTask>tasksToStart){...while(this.m_runningTaskCount>0){yieldreturn1;this.m_runningTaskCount--;IAsyncResultasyncResult=this.m_asyncEnumerator.DequeueAsyncResult();AsyncTaskfinishedTask=(AsyncTask)asyncResult.AsyncState;try{finishedTask.End(asyncResult,false,finishedTask.Context);finishedTask.Status=AsyncTaskStatus.Succeeded;if(this.Status==DispatchStatus.Dispatching){this.StartSuccessors(finishedTask);}finishedTask.Close();}catch(AsyncTaskExceptionex){if(this.HandleTaskFailure(ex.Task,ex.InnerException))break;}catch(Exceptionex){if(this.HandleTaskFailure(finishedTask,ex))break;}}this.Status=DispatchStatus.Finished;}在Start办法中,假如乐成倡议了这个异步哀求,则会将m_runningTaskCount的数值加一,以此暗示正在实行(切实地说,是已经“入手下手”但还没有举行“停止”处置)的异步义务数量。while轮回体每实行一遍,则暗示处置完一个异步哀求。因而一样平常情形下,在没有处置完一切异步请求的时分while轮回体味不休实行。与之前WebRequest的示例类似,AsyncTask对象作为AsyncState保留在IAsyncResult对象中——因为增添了AsyncTask这一笼统层,因而我们乐成地将一切异步操纵的处置体例一致了起来。
接着便顺次挪用End托付(请注重cancelling参数为false)、设置属性、而且在AsyncTaskDispatcher为Dispatching形态时利用StartSuccessors办法来分拨可实行的后继义务——AsyncTaskDispatcher的形态也有大概是Waiting,这暗示已有义务堕落,此时正在守候已入手下手的义务完成,这类情形下就不该该倡议新的异步义务了。值得注重的是,用户完成的End托付大概会抛出非常,而StartSuccessors办法也大概抛出AsyncTaskException以暗示某个异步义务启动失利。这时候就要利用HandleTaskFailure办法来处置非常,而且在符合的时分当即停止全部分拨操纵(跳出轮回)。
跳出while轮回则暗示全部派送操纵已完成,此时天然要将AsyncTaskDispatcher的形态设为Finished。
而最初剩下的,只是用于启动义务的Start办法,用于作废义务的CancelTask办法,和倡议后继义务的StartSuccessors办法了:
privatevoidStart(AsyncTasktask){DispatchPolicypolicy;try{policy=task.Predicate==null?DispatchPolicy.Normal:task.Predicate(task.Context);}catch(Exceptionex){thrownewAsyncTaskException(task,ex);}if(policy==DispatchPolicy.Normal){try{task.Begin(this.m_asyncEnumerator.EndVoid(0,this.CancelTask),task,task.Context);this.m_runningTaskCount++;task.Status=AsyncTaskStatus.Executing;}catch(Exceptionex){thrownewAsyncTaskException(task,ex);}}elseif(policy==DispatchPolicy.MarkAsCancelled){task.Status=AsyncTaskStatus.MarkedAsCancelled;task.Close();}else//policy==DispatchPolicy.Succeeded{task.Status=AsyncTaskStatus.MarkedAsSucceeded;this.StartSuccessors(task);task.Close();}}privatevoidStartSuccessors(AsyncTasktask){Func<AsyncTask,bool>predicate=t=>t.Status==AsyncTaskStatus.Pending&&t.DependenciesSucceeded;foreach(AsyncTasksuccessorintask.Successors.Where(predicate)){this.Start(successor);}}privatevoidCancelTask(IAsyncResultasyncResult){AsyncTasktask=(AsyncTask)asyncResult.AsyncState;try{task.End(asyncResult,true,task.Context);}catch{}finally{this.m_runningTaskCount--;task.Status=AsyncTaskStatus.Cancelled;task.Close();}}在Start办法中,起首猎取异步义务的Predicate托付的实行了局,并依据这个了局选择是将以后异步义务举行一般处置,仍是标志为“取消”或“乐成”。假如应当一般实行,则挪用Begin托付以倡议异步义务,把义务形态标志为Executing,并将m_runningTaskCount计数加一。假如选择标志为“乐成”,那末还必要挪用StartSuccessors来倡议后继义务,天然在StartSuccessors办法中也是利用Start办法来倡议单个义务——这是一种直接递回,利用“深度优先”的体例倡议一切依附已全体完成的异步哀求。因为Start办法必要抛出AsyncTaskException来暗示义务堕落,因而在每段由用户完成的逻辑(即Predicate和Begin托付)实行时都要当心地捕捉非常。
值得一提的是,假如必要利用AsyncEnumerator的Cancel办法来作废已倡议的异步义务,那末在从AsyncEnumerator猎取异步回调托付(AsyncCallback对象)的时分还必需供应一个托付作为作废这个义务时的回调函数。这即是CancelTask办法的感化,在CancelTask办法中也会挪用End托付(请注重cancelling参数为true),以确保资本可以被准确开释。实行End托付时抛出的任何非常城市被冷静“吞下”。一个义务被作废以后,它的形态会被修正为Cancelled,最初则被封闭。
至此,AsyncTaskDispatcher已全体完成到这里就告一段落了。可见,有了AsyncEnumerator的帮忙,完成如许一个组件其实不那末坚苦,从头到尾统共只要200多行代码。现实上,写今朝这篇文章所损耗的工夫和精神已数倍于完成一个完全的AsyncTaskDispatcher。固然,今朝的完成远不完善,它固然较好地完成了有依附干系的多个异步操纵之间的合作挪用,可是还短少一些有效的功效。比方,您大概必要在分拨过程当中静态增加新的义务,或是改动义务之间的依附干系;并且,关于异步操纵常常城市指定一个超不时间,惋惜今朝的AsyncTaskDispatcher其实不包括超时功效。
您能够在这里取得AsyncTaskDispatcher的完全代码,而且依据必要增加任何功效——特别是方才提到的缺点,完成起来实践其实不坚苦。
AsyncTaskDispatcher的利用

如今我们基于AsyncTaskDispatcher来从头完成上一篇文章中提到的场景。假定您在开辟一个ASP.NET页面用于展现一篇文章,个中必要显现各类信息:

[*]文章内容
[*]批评信息
[*]对批评内容举行打分的用户
[*]打分者的保藏
因为程序架构的缘故原由,数据必要从各个分歧服务或数据源中猎取(这是个很罕见的情形)。因而,程序中已筹办了以下的数据读取接口:

[*]Begin/EndGetContent:依据文章ID(Int32),猎取文章内容(String)
[*]Begin/EndGetComments:依据文章ID(Int32),猎取一切批评(IEnumerable
[*]Begin/EndGetUsers:依据多个用户ID(IEnumerable),猎取一批用户(Dictionary
[*]Begin/EndGetCommentRaters:依据多个批评ID(IEnumerable),猎取一切打分者(IEnumerable)
[*]Begin/EndGetFavorites:依据多个用户ID(IEnumerable),猎取一切保藏(IEnumerable)
我们能够容易得出五个异步操纵之间的依附情况:

<br>
因而,我们能够编写以下的代码。请注重,我们利用异步义务的id来暗示它们之间的依附干系:
privatevoidRegisterAsyncTasks(AsyncTaskDispatcherdispatcher,intarticleId){//猎取文章内容stringtaskGetContent="getcontent";dispatcher.RegisterTask(taskGetContent,//义务ID(cb,state,context)=>//Begin托付对象{returnService.BeginGetContent(articleId,cb,state);},(ar,cancelling,context)=>//End托付对象{this.Content=Service.EndGetContent(ar);});//猎取批评stringtaskGetComments="getcomments";IEnumerable<Comment>comments=null;dispatcher.RegisterTask(taskGetComments,(cb,state,context)=>{returnService.BeginGetComments(articleId,cb,state);},(ar,cancelling,context)=>{comments=Service.EndGetComments(ar);});//猎取批评者信息,并分离批评绑定至控件stringtaskGetCommentUsers="getcommentusers";dispatcher.RegisterTask(taskGetCommentUsers,(cb,state,context)=>{returnService.BeginGetUsers(comments.Select(c=>c.UserID),cb,state);},(ar,cancelling,context)=>{varusers=Service.EndGetUsers(ar);this.rptComments.DataSource=fromcincommentsselectnew{Comment=c,User=users};this.rptComments.DataBind();},taskGetComments);//指定义务之间的依附干系//猎取批评的打分者,并绑定至控件stringtaskGetCommentRaters="getcommentraters";IEnumerable<User>raters=null;dispatcher.RegisterTask(taskGetCommentRaters,(cb,state,context)=>{returnService.BeginGetCommentRaters(comments.Select(c=>c.CommentID),cb,state);},(ar,cancelling,context)=>{raters=Service.EndGetCommentRaters(ar);this.rptRaters.DataSource=raters;this.rptRaters.DataBind();},taskGetComments);//猎取打分者的保藏内容,并绑定至控件stringtaskGetFavorites="getfavorites";dispatcher.RegisterTask(taskGetFavorites,(cb,state,context)=>{returnService.BeginGetFavorites(raters.Select(u=>u.UserID),cb,state);},(ar,cancelling,context)=>{this.rptFavorites.DataSource=Service.EndGetFavorites(ar);this.rptFavorites.DataBind();},taskGetCommentRaters);}与之前的作法比拟,仿佛代码量进步了,可是察看后能够发明,多出来的代码实在都是在创立匿名的托付对象,而一个个匿名的托付对象将代码举行了有层次的支解,并充实使用“匿名办法”构成的闭包,使各托付对象可以共享“挪用仓库”上的数据。如今的完成利用了一种直不雅的体例体现了各别步操纵之间的依附干系,代码一会儿变得层次明晰,易于保护了。别的另有一点十分主要:固然异步义务为“并行”实行,可是个中一切的托付对象只会顺次挪用,因而开辟职员能够宁神地编写代码,而不必忧虑线程平安方面的成绩。
我们能够把下面的代码分离ASP.NETWebForm页面的异步特征一同利用:
protectedvoidPage_Load(objectsender,EventArgse){this.AddOnPreRenderCompleteAsync(newBeginEventHandler(BeginAsyncOperation),newEndEventHandler(EndAsyncOperation));}privateIAsyncResultBeginAsyncOperation(objectsender,EventArgse,AsyncCallbackcallback,objectextraData){this.m_dispatcher=newAsyncTaskDispatcher();this.RegisterAsyncTasks(this.m_dispatcher,1);returnthis.m_dispatcher.BeginDispatch(callback,extraData);}privatevoidEndAsyncOperation(IAsyncResultar){this.m_dispatcher.EndDispatch(ar);}这个页面与AsyncTaskDispatcher的源代码同时公布,而且增添了一些复杂的工夫统计代码。您会发明,底本利用“串行”体例必要10秒钟才干完成的义务,利用现在的“并行”体例只需6秒钟便可完成:

[*]GetContent:00:00:00-00:00:02.0010000
[*]GetComments:00:00:00.0010000-00:00:02.0010000
[*]GetCommentUsers:00:00:02.0010000-00:00:04.0010000
[*]GetCommentRaters:00:00:02.0010000-00:00:04.0010000
[*]GetFavorites:00:00:04.0010000-00:00:06.0010000
这与上一篇文章中提到的“幻想情形”完整分歧:

<br>
总结

因为CCR和AsyncEnumerator难以“并行”地实行异步代码,因而我们必要提出新的办理计划来满意这方面的需求。在AsyncEnumerator的基本上开辟一个AsyncTaskDispatcher其实不坚苦,可是这个组件可以无效地简化多个异步操纵之间的合作调用。一样平常来讲,如许的做法可以使使用程序的功能与伸缩性失掉对照分明的进步。AsyncTaskDispatcher的代码在MSDNCodeGallery上完整公然,您能够自在修正,使它更好地满意您的需求。
相干文章:简化异步操纵(上)──利用CCR和AsyncEnumerator简化异步操纵
本文出自:http://www.infoq.com/cn/articles/ccr-async-partii
既然话题已经抄起,我打算今晚发篇博文再引导一下舆论方向,使它再火两天,抛砖引玉,而且赵劼先生一直在跟帖,使.NET阵营的我感到万分难得。

老尸 发表于 2015-1-30 05:55:08

最强的技术支持WebService,而且有.NET的所有library做后盾。而且ASP.NET在.NET3.5中还有微软专门为AJAX开发的功能--ASP.NETAJAX。

透明 发表于 2015-1-30 13:18:21

它可通过内置的组件实现更强大的功能,如使用A-DO可以轻松地访问数据库。

莫相离 发表于 2015-1-31 08:12:17

逐步缩小出错代码段的范围,最终确定错误代码的位置。

飘灵儿 发表于 2015-2-6 18:45:37

Servlet的形式和前面讲的CGI差不多,它是HTML代码和后台程序分开的。它们的启动原理也差不多,都是服务器接到客户端的请求后,进行应答。不同的是,CGI对每个客户请求都打开一个进程(Process)。

柔情似水 发表于 2015-2-7 13:04:14

ASP(ActiveServerPages)是Microsfot公司1996年11月推出的WEB应用程序开发技术,它既不是一种程序语言,也不是一种开发工具,而是一种技术框架,不须使用微软的产品就能编写它的代码。

爱飞 发表于 2015-2-21 22:16:01

平台无关性是PHP的最大优点,但是在优点的背后,还是有一些小小的缺点的。如果在PHP中不使用ODBC,而用其自带的数据库函数(这样的效率要比使用ODBC高)来连接数据库的话,使用不同的数据库,PHP的函数名不能统一。这样,使得程序的移植变得有些麻烦。不过,作为目前应用最为广泛的一种后台语言,PHP的优点还是异常明显的。

灵魂腐蚀 发表于 2015-3-6 21:59:36

asp.net最主要特性包括:◆编程代码更简洁◆网站可实现的功能更强大◆运行效率高◆节省服务器的动作资源

分手快乐 发表于 2015-3-11 22:00:10

在调试JSP代码时,如果程序出错,JSP服务器会返回出错信息,并在浏览器中显示。这时,由于JSP是先被转换成Servlet后再运行的,所以,浏览器中所显示的代码出错的行数并不是JSP源代码的行数。

再见西城 发表于 2015-3-19 14:39:16

主流网站开发语言之JSP:JSP和Servlet要放在一起讲,是因为它们都是Sun公司的J2EE(Java2platformEnterpriseEdition)应用体系中的一部分。

冷月葬花魂 发表于 2015-3-28 07:46:08

碰到复杂点的问题都不知道能不能解决,现在有点实力的公司都选择自已在开源的基础上做开发。但没听说过有人在IIS上做改进的,windows、sqlserver集群方面的应用也很少见。
页: [1]
查看完整版本: ASP.NET网站制作之简化异步操纵(下)──构建AsyncTaskDispatcher简化多个异步操纵之间的合作挪用仓酷 ...