ASP.NET网站制作之异步代办署理: 利用异步代办署理库举行基于脚色...
呵呵,那你就关注微软的招聘信息以及别人的招聘经验啊,还有也不一定去做技术的,你如果真的想去就多了解了解。(其实我的意思是说想到微软做技术是很不容易的。 跟着多核处置器在市场上的日趋提高,它已普遍用于服务器、台式机和便携式盘算机,代码并行化的主要性也亘古未有地凸显出来。为了满意这一关头需求,VisualStudio2010引进了多少新的办法,匡助C++开辟职员使用新的并交运行时和新的并行编程模子带来的这些功效。但是,开辟职员面对的一个次要停滞是断定哪一种编程模子合适于他们的使用程序。准确的模子能够充实使用底层并行性,不外也必要从头思索程序布局和实践的实行体例。 今朝,最多见的并行编程模子触及到通用的并发感知容器和并行轮回迭代等算法。固然这些传统手艺功效壮大,可扩大使用程序来共同多核盘算机利用,但它们并未办理影响并行功能的其他次要要素之一,那就是不休加深的提早影响。因为并行手艺加速盘算速率并将盘算散布在多个内核之间,因而,Amdahl定律(wikipedia.org/wiki/Amdahl"s_law)告知我们功能改善遭到实行速率最慢的那一部分制约。在很多情形下,守候来自I/O(比方磁盘或收集)的数据所花的工夫比例愈来愈年夜。基于脚色的编程模子可以很好地处置提早等成绩,这些模子最后是在二十世纪七十年月初引进的,目标是使用具有成百上千个自力处置器的高度并行盘算机资本。脚色模子面前的基础观点是将使用程序的各个组件视为独自的脚色,这些脚色能够经由过程发送、吸收和处置动静与外界交互。
比来,跟着大批多核处置器的使用,脚色模子已作为一种削减提早、完成高效并行实行的无效办法从头出面。VisualStudio2010引进了异步代办署理库(AAL),这是一个使人冲动的基于脚色的新模子,它具有动静传送接口,在该模子中代办署理就是脚色。AAL使开辟职员能够经由过程加倍以数据流为中央的体例计划本人的使用程序。如许的计划一般有益于在守候数据时无效利用提早。
在本文中,我们将概述AAL并先容怎样在使用程序中利用它。
并发运转时
VisualStudio2010和AAL中并发撑持的基本是新的并发运转时,该运转时作为VisualStudio2010中C运转时(CRT)的一部分供应。并发运转时供应和谐义务企图程序和资本办理器,后者对盘算机的底层资本有深切懂得。这就同意运转时以负载均衡的体例在全部多核盘算机中实行义务。
扼要地展现了VisualStudio2010中对本机代码并发的撑持。企图程序是断定什么时候何地实行义务的次要组件。它借助资本办理器搜集的信息来充实天时用实行资本。只管使用程序和库也能够间接与运转时交互,但它们自己次要仍是经由过程两个位于企图程序之上的编程模子(即AAL和并行形式库(PPL))与并发运转时交互。
并发运转时
PPL供应更加传统的并行手艺(比方parallel_for和parallel_for_eachconstructs)、可辨认运转时的锁和并发数据布局(比方行列和向量)。固然PPL不是本文先容的重点,但它也是一种功效壮大的工具,开辟职员能够将其与AAL中引进的一切新办法共同利用。有关PPL的具体信息,请参阅2009年2月刊载的《利用C++的Windows》专栏(msdn.microsoft.com/magazine/dd434652)。
比拟之下,AAL可以在更初级别以分歧于传统手艺的角度来并行化使用程序。开辟职员必要从待处置数据的角度思索使用程序,并思索怎样将数据处置分开到可并行实行的组件或阶段中。
AAL供应两个次要组件:动静传送框架和异步代办署理。
动静传送框架包含一组动静块,用于吸收、处置和传布动静。经由过程将动静块串联起来,可创立可以同时实行的事情管道。
异步代办署理是经由过程吸收动静、在本人保护的形态下实行当地事情和发送动静,以此与外界交互的脚色。
这两个组件分离在一同,使开辟职员可以在数据流而不是把持流方面使用并行性,并经由过程更高效地利用并行资本来改良对提早的容忍度。
动静传送框架
AAL的第一个主要组件是动静传送框架,该框架是帮忙开辟数据流收集以便将事情管道化的一组机关。将事情管道化是数据流模子的基础部分,由于它同意将事情分化为多个自力的阶段,只需数据停当即可对流数据举行并行处置。当一个阶段的数据处置停止时,该阶段可将数据传送到下一阶段,同时第一个阶段寻觅要处置的新数据。
我们以设置传出动静格局并检察动静中是不是存在不妥内容的电子邮件使用程序为例。这类范例操纵的代码显现以下:
std::foreach(reader.begin();reader.end();
[](conststring&word){
autow1=censor(word);
autow2=format(w1);
writer.write_word(w2);
});
关于电子邮件中的每一个词,该使用程序都必要反省它是不是存在于检察词的字典中,假如存在则予以交换。然后,代码依据一组引导准绳设置每一个词的格局。
这类计划中存在大批固有的并行性。可是,传统并行手艺还不克不及满意请求。比方,一种复杂的办法是对文本中的字符串利用parallel_for_each算法,检察这些字符串并设置格局。
这类办理计划的第一个次要拦阻是必需读取全部文件,以便迭代器可以准确地分别事情。
强迫读取全部文件会招致历程遭到I/O的限定,而且会下降并行效力。固然,您可使用智能迭代器将词的处置与读取输出的操纵堆叠举行。
传统并行办法的第二个次要成绩是排序。明显,关于电子邮件来讲,对文本的并行处置必需坚持文本按次,不然会完整没法了解邮件的寄义。为了坚持文本按次,parallel_for_each手艺会发生同步弛缓冲方面的大批开支,而这一历程可由AAL主动处置。
经由过程接纳管道手艺处置邮件,您能够制止上述两个成绩,同时还能使用并行才能。请看一下,个中创立了一个复杂管道。在此示例中,使用程序的次要义务(检察和设置格局)被分为两个阶段。第一个阶段吸收字符串并在检察词的字典中查找该字符串。假如找到婚配项,检察块会利用字典中的另外一个词交换该字符串。不然,它会输入已输出的统一封邮件。一样,在第二个阶段中,格局设置块吸收每一个词并将其得当地设置为特定款式。
电子邮件处置管道
此示例可在以下几个方面从数据流办法获益。起首,因为它不必要在处置前读取整封邮件,邮件中的字符串能够经由过程检察和设置格局阶段当即入手下手流处置。其次,管道处置同意一个字符串由设置格局块举行处置,同时下一个字符串由检察块举行处置。最初,因为字符串的处置按次是它们在原文中呈现的按次,因而不必要实行分外的同步。
动静块
动静块吸收、处置、存储和传布动静。动静块有三种情势:源、方针和传布器。源只能传布动静,而方针可以吸收、存储和处置动静。年夜多半块都是传布器,既是源又是方针。换句话说,它们可以吸收、存储和处置动静,也能够转而将这些动静发送进来。
AAL包括一组动静块基元,可以满意开辟职员的年夜部分利用需求。扼要概述了AAL中包含的一切动静块。不外该模子仍旧是开放式的,因而,假如您的使用程序必要具有特定举动的动静块,能够本人编写可与一切预界说块交互的自界说块。每一个块都有各自处置、存储和传布动静的独占特性。
AAL动静块
动静块用处unbounded_buffer<Type>存储不限数目的动静并将其传布到方针。overwrite_buffer<Type>存储一条动静,每次有新动静传布出去时城市掩盖该动静,然后将其播送到方针。single_assignment<Type>存储一条一次写进的动静,然后将其播送到方针。transformer<Input,Output>吸收一条范例为Input的动静,然后运转用户供应的函数将其转换为范例为Output的动静。将这条转换后的动静传布到方针。
call<Type>吸收一条动静,然后利用该动静的负载作为参数来运转用户供应的函数。这类块是地道的动静方针。
timer<Type>在用户界说的工夫量以后将动静传布到方针。能够是反复或非反复的块。
这类块是地道的动静源。
choice<Type1,Type2,...>吸收来自多品种型的多个源的动静,但只承受来自传布到所选范例的第一个块的动静。join<Type>吸收来自多个源的动静,将它们组合起来输入单条动静。异步守候从各个源输出的动静筹办停当。
multitype_join<Type1,Type2,...>吸收来自多品种型的多个源的动静,将它们组合起来。异步守候从各个源输出的动静筹办停当。
AAL供应的动静块基元的一个次要上风是它们的可组合性。因而,您能够依据所需举动举行组合。比方,您能够轻松创立将多个输出增加到一同的块,办法是将转换器块附加到连接块的开端。当连接块乐成检索到来自它的各个源的动静时,可将动静传送给转换器,而转换器将汇总动静负载。
您也能够将反复的计时器块毗连为连接块的源。这会构成一个限定动静的块,只在计时器块触发其动静时同意动静经由过程。中申明了这两种可组合块。
组合来自基元的加法器块与动静限定块
创立动静传送管道
如今,我们来看看创立上文所示的动静块管道的代码。我们能够用两个转换器动静块交换此管道,如所示。转换器块的用处是吸收特定范例的动静并抵消息实行用户界说的函数,这一操纵可修正动静负载乃至完全变动动静范例。比方,检察块将包括字符串的动静作为输出吸收,然后必要对其举行处置。
动静块管道
中显现了创立和毗连动静块的代码。此代码从实例化两个转换器动静块入手下手。检察块机关函数中的C++0xlambda参数界说转换函数,该转换函数在字典外调找动静的存储输出字符串,看看是不是应变动为其他字符串。体系前往了局字符串,然后在检察块内将其封装成单条动静并从该块传布进来。除非转换器块的输入是格局设置函数变动过的字符串,不然关于格局设置转换器块会接纳相似路子。
复杂动静管道
dictionarydict;
transformer<string,string>
censor([&dict](conststring&s)->string{
stringresult=s;
autoiter=dict.find(s);
if(iter!=dict.end()){
result= iter->second;
}
returnresult;
});
transformer<string,string>
format([](conststring&s)->string{
stringresult=s;
for(string::size_typei=0;i<s.size();i++){
result=(char)Format(s);
}
returnresult;
});
censor.link_target(&format);
asend(&censor,"foo");
stringnewStr=receive(format);
printf("%s
",newStr);
两个块实例化今后,下一行代码经由过程对检察块挪用link_target办法,将两个块链接到一同。每一个源块和传布器块都有link_target办法,用于断定源应当将它的动静传布到哪些动静块。
检察块和格局设置块链接到一同后,转换函数会处置传布到检察块的任何动静,天生的动静将隐式传送到格局设置块举行处置。假如动静块是没有毗连方针的源或传布器,它能够按特定于块的体例存储动静,直到链接了方针或动静被检索。
示例代码的最初三行显现将动静初始化到块中和从块中检索动静的历程。AAL中有两种动静初始化API:send和asend。它们分离将动静同步或异步输出块中。
次要区分是,当send挪用前往时,包管已将动静推送到块,而且已经由过程块将动静发送到所需方针。asend挪用能够当即前往,而且同意并发运转时企图传布。一样地,AAL中有两种动静检索API:receive和try_receive。receive办法在动静抵达前一直处于制止形态,而try_receive则会在没法检索动静时当即前往。
如所示,字符串“foo”会异步发送到检察块。检察块将吸收该动静,反省其字符串是不是存在于检察词的字典中,然后将了局字符串传布到动静中。接着,了局字符串被传送到格局设置块,后者吸收该字符串,将每一个字母酿成年夜写,然后因为没有方针而保存到动静中。当挪用receive时,将从格局设置块中猎取该动静。如许,假定字典中没有“foo”,此示例的输入将是“FOO”。固然此示例只是经由过程收集推送单个字符串,但能够看到输出字符串流是怎样构成实行管道的。
请看一下此动静示例,注重动静自己分明短少援用。动静只是一个信封,个中封装要在数据流收集中传送的数据。动静传送自己是经由过程供应和承受历程来处置的。当动静块收到动静时,可以以任何想要的体例存储该动静。假如稍后要将动静发送进来,它会将该动静供应给每一个毗连的方针。若要真正将动静送出,吸收方必需承受供应的动静,以完成该事件。动静在块间传送的全部历程是由并发运转时企图和实行的义务来企图和处置的。
动静块传布
如今,您已懂得动静块是怎样创立和联系关系在一同的,和怎样将动静初始化到每一个块中并从中检索动静。接上去让我们复杂懂得一下动静怎样在块间传送,和并发运转时怎样成为AAL的中心。
利用动静块或AAL纷歧定必要懂得此信息,但它有助于加深抵消息传送协定事情体例及其利用体例的了解。在本节的其他部分,我将先容传布器块,由于它们既是源又是方针。明显,地道的源块或地道的方针块只是传布器块完成的子集。
在外部,每一个传布器块都有一个动静输出行列和另外一个特定于块的动静存储容器。链接到此传布器块的其他块会发送存储在输出行列中的动静。
比方,在中,检察转换器块有一个输出行列,该行列以后存储包括字符串str6的动静。实践转换器自己包括两个动静:str4和str5。由于这是转换器,以是它的特定于块的存储是另外一行列。分歧的块范例能够有分歧的存储容器。比方,overwrite_buffer块只存储一直会被掩盖的单条动静。
动静传送协定
从某个链接的源(或send/asendAPI)向块供应动静时,此块起首会反省选择器函数,以决意是不是承受动静。假如决意承受动静,则将动静放进输出行列。选择器是一个可选函数,可传送到前往布尔值的每一个方针的机关函数或传布器块中,该布尔值决意是不是应承受某个源供应的动静。假如动静被回绝,该源会持续向下一个方针供应动静。
一旦动静放进输出行列,它的源块就不再保存此动静。不外,承受块还没有筹办好传布动静。因而在守候处置时,动静能够缓冲到输出行列中。
当动静抵达某个动静块的输出行列时,并发运转时企图程序管帐同等个轻型义务(LWT)。此LWT有两重目标。起首,它必需将动静从输出行列移到块的外部存储中(我们称之为动静处置)。其次,它还必需实验将动静传布就任意方针(我们称之为动静传布)。
比方,在中,输出行列中存在提醒体系企图LWT的动静。接上去LWT会处置动静,办法是先抵消息实行用户供应的转换器函数,在检察字符串字典中反省该动静,然后将它移到块的存储缓冲区。
将动静转移到存储缓冲区以后,LWT入手下手实行传布步骤,将动静发送到方针设置格局块。在这类情形下,因为动静str4位于转换器的前端,它会先传布到格局设置块,然后再传布下一条动静str5。一样的全部历程会在格局设置块中产生。
依据动静块的范例,动静处置体例会有所分歧。比方,unbounded_buffer只要将动静移到存储缓冲区的复杂处置步骤。转换器处置动静的体例是先抵消息挪用用户界说的函数,然后再将其移到存储缓冲区。其他块的处置体例乃至更庞大,比方连接,它必需组合来自分歧源的多条动静,然后将它们存储到缓冲区中以备传布。
就功能效力而言,AAL在创立LWT方面是智能化的,因而每次只会为每一个动静块企图一个LWT。假如处置LWT处于举动形态时有更多动静抵达输出行列,LWT会持续拔取并处置这些动静。因而,如所示,假如动静str7进进输出行列时转换器的LWT仍在处置,它将拔取并处置此动静,而不是启动新的处置和传布义务。
每一个动静块都有各自用于把持处置和传布的LWT,这是此计划的中心,它同意动静传送框架按数据流的体例将事情管道化。由于每一个动静块在本人的LWT中处置和传布动静,以是AAL能够将块相互分别,并同意跨多个块实行并行事情。每一个LWT必需只将本人的动静传布到方针块的输出行列,而每一个方针仅企图一个LWT来处置本人的输出。利用单个LWT处置和传布动静可确保为动静块坚持动静序次。
异步代办署理
AAL的第二个次要组件是异步代办署理。异步代办署理是粗粒度使用程序组件,专门用于异步处置较年夜型的盘算义务和I/O。代办署理应当能够与其他代办署理通讯,并启动较初级其余并行处置。这些代办署理是断绝的,由于它们关于外界的了解完整包括在类中,它们能够经由过程动静传送与其他使用程序组件通讯。代办署理自己被企图为并发运转时外部的义务。这同意它们共同同时实行的其他事情来制止和运转。
异步代办署理有流动性命周期,如所示。能够监督和守候今生命周期。绿色形态暗示运转形态,而白色形态暗示停止形态。开辟职员可经由过程从代办署理基类派生的体例创立本人的代办署理。
异步代办署理性命周期
三种基类函数(start、cancel和done)可转换代办署理的分歧形态。一旦完成机关,代办署理即处于已创立形态。启动代办署理和启动线程相似。除非对代办署理挪用start办法,不然代办署理不会实行任何操纵。此时,代办署理将依据企图实行,并进进可运转形态。
当并发运转时拔取此代办署理时,它会进进已启动形态并持续运转,直到用户挪用done办法,该办法唆使它的事情已完成。已企图但还没有启动代办署理时,挪用cancel会将代办署理转换成已作废形态,代办署理将不再实行。
让我们回忆一下电子邮件选择示例。在此示例中,管道式动静块将数据流引进使用程序,并进步本人并行处置词语的才能。可是,此示例没有显现怎样把持处置电子邮件自己的I/O,和怎样将它们分化成字符串流,以便管道举行处置。别的,一旦字符勾通过管道,必需举行搜集,以便以新的已检察和已设置格局的形态从头编写文本。这就是代办署理能够发扬感化的中央,目标是匡助容忍I/O提早差别。
比方,请看一下电子邮件管道的开端。此时,字符串正由格局设置块输入,并必要写进邮箱的文件中。显现输入代办署理怎样捕捉字符串和创立输入电子邮件。WriterAgent的run函数吸收来自轮回中的格局设置块的动静。
代办署理捕捉格局设置块的输入
此使用程序中的年夜部分处置事情是利用数据流完成的,而WriterAgent则显现了怎样在程序中引进某些把持流。比方,当文件开头动静抵达时,依据吸收的输出字符串,WriterAgent必需有分歧的举动;它必需晓得中断操纵。0中显现了WriterAgent的代码。
0WriterAgent
classWriterAgent:publicagent{
public:
WriterAgent(ISource<string>*src):m_source(src){
}
~WriterAgent(){
agent::wait(this);
}
virtualvoidrun(){
FILE*stream;
fopen_s(&stream,...
);
strings;
stringeof("EOF");
while(!feof(stream)&&((s=receive(m_source))!=eof)){
write_string(stream,s);
}
fclose(stream);
done();
}
private:
ISource<string>*m_source;
};
此代码有几个值得存眷的中央。起首是析构函数中对静态函数agent::wait的挪用。可使用指向任何代办署理的指针挪用此函数,而且此函数会一向处于制止形态,直到代办署理进进一种停止形态(done或canceled)。固然并非一切代办署理都必要在析构函数中挪用wait,但多半情形下应让它完成,如许可确保析构时期理不再实行任何代码。
其次,此代码的风趣部分是run办法自己。此办法界说代办署理的主实行历程。在此代码中,代办署理正在处置从源(在本例中是格局设置块)读取的字符串的写出操纵。
最初,请注重run办法的最初一行,此行是对代办署理函数done的挪用。对done办法的挪用可将代办署理从运转形态变化成完成形态。在年夜多半情形下,需在run办法开端挪用此办法。不外,在某些情形下,使用程序大概但愿利用代办署理来设置形态。比方在数据流收集中,该收集在run办法保存期后仍应坚持举动形态。
将一切内容整合在一同
如今,我们已创立了动静传送管道对字符串举行选择和设置格局,创立了输入代办署理对字符串举行处置,我们能够将具有类似举动的输出代办署理附加到输入代办署理。1举例申明了此使用程序怎样组合到一同。
1用于处置电子邮件的代办署理
代办署理处置的一个上风是可以在使用程序中利用异步脚色。如许,当数据抵达并守候处置时,输出代办署理将异步入手下手经由过程管道发送字符串,输入代办署理一样能够读取和输入文件。这些脚色能够完整自力地入手下手和中断处置,而且完整由数据驱动。此类举动在很多情形下十分有效,出格是在提早驱动和异步I/O情形下,比方电子邮件处置示例。
在此示例中,我增加了另外一个代办署理ReaderAgent,它与WriterAgent事情体例相似,分歧的是,它处置I/O以读取电子邮件并向收集发送字符串。2中显现了ReaderAgent的代码。
2ReaderAgent
classReaderAgent:publicagent{
public:
ReaderAgent(ITarget<string>*target):m_target(target){
}
~ReaderAgent(){
agent::wait(this);
}
virtualvoidrun(){
FILE*stream;
fopen_s(&stream,...);
while(!feof(stream)){
asend(m_target,read_word(stream));
}
fclose(stream);
asend(m_target,string("eof"));
done();
}
private:
ITarget<string>*m_target;
};
如今,我们已有ReaderAgent和WriterAgent对程序I/O举行异步处置,只需将它们链接至收集中的转换器块,即可入手下手处置。将两个块链接在一同以后便可轻松完成此义务:
censor.link_target(&format);
ReaderAgentr(&censor);
r.start();
WriterAgentw(&format);
w.start();
ReaderAgent是经由过程对检察的援用创立的,因而能够准确地将动静发送到该代办署理,而WriterAgent是经由过程对格局设置的援用创立的,因而能够检索动静。每一个代办署理都利用启动API举行启动,该API布置代办署理在并发运转时中实行。每一个代办署理都在本人的析构函数中挪用agent::wait(this),因而要比及两个代办署理都抵达完成形态才会入手下手实行。
同步
本文旨在让读者开端懂得内置于VisualStudio2010中的基于脚色的编程和数据流管道的一些新功效。我们勉励您试用一下。
假如深切探究的话,能够懂得到很多本文没法逐一胪陈的其他功效:自界说动静块创立和选择动静等等。MSDN上的并行盘算开辟中央(msdn.microsoft.com/concurrency)包括更多有关这一使人镇静的新编程模子怎样匡助您以全新体例并行化程序的具体信息和利用步骤。
在CSDN里搜索一下“初学”两字,竟有三百余篇帖子(也许更多)。有些帖子说,有了asp的基础,只要15天就能很熟悉了,我甚感自己的愚钝。更多帖子是向大家请教初学者适合看书。两个多月的时间(当然平常杂事比较多。 asp.net最主要特性包括:◆编程代码更简洁◆网站可实现的功能更强大◆运行效率高◆节省服务器的动作资源 Servlet却在响应第一个请求的时候被载入,一旦Servlet被载入,便处于已执行状态。对于以后其他用户的请求,它并不打开进程,而是打开一个线程(Thread),将结果发送给客户。由于线程与线程之间可以通过生成自己的父线程(ParentThread)来实现资源共享,这样就减轻了服务器的负担,所以,JavaServlet可以用来做大规模的应用服务。 能产生和执行动态、交互式、高效率的站占服务器的应用程序。运用ASP可将VBscript、javascript等脚本语言嵌入到HTML中,便可快速完成网站的应用程序,无需编译,可在服务器端直接执行。容易编写。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。 通过这次激烈的讨论,我从大家身上学到了太多,开阔了眼界,不管是支持我的还是骂我的,都感谢你们。 ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。 平台无关性是PHP的最大优点,但是在优点的背后,还是有一些小小的缺点的。如果在PHP中不使用ODBC,而用其自带的数据库函数(这样的效率要比使用ODBC高)来连接数据库的话,使用不同的数据库,PHP的函数名不能统一。这样,使得程序的移植变得有些麻烦。不过,作为目前应用最为广泛的一种后台语言,PHP的优点还是异常明显的。
页:
[1]