C同步方法和异步方法的区别

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

同步方法和异步方法的区别同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作林sir提示:在异步方法里面,注意的是回调函数!搞定了回调函数就基本了解异步编程。异步编程的基础:同步方法和异步方法的区别同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作异步编程概览.NETFramework允许您异步调用任何方法。定义与您需要调用的方法具有相同签名的委托;公共语言运行库将自动为该委托定义具有适当签名的BeginInvoke和EndInvoke方法。BeginInvoke方法用于启动异步调用。它与您需要异步执行的方法具有相同的参数,只不过还有两个额外的参数(将在稍后描述)。BeginInvoke立即返回,不等待异步调用完成。BeginInvoke返回IasyncResult,可用于监视调用进度。EndInvoke方法用于检索异步调用结果。调用BeginInvoke后可随时调用EndInvoke方法;如果异步调用未完成,EndInvoke将一直阻塞到异步调用完成。EndInvoke的参数包括您需要异步执行的方法的out和ref参数(在VisualBasic中为OutByRef和ByRef)以及由BeginInvoke返回的IAsyncResult。四种使用BeginInvoke和EndInvoke进行异步调用的常用方法。调用了BeginInvoke后,可以:1.进行某些操作,然后调用EndInvoke一直阻塞到调用完成。2.使用IAsyncResult.AsyncWaitHandle获取WaitHandle,使用它的WaitOne方法将执行一直阻塞到发出WaitHandle信号,然后调用EndInvoke。这里主要是主程序等待异步方法,等待异步方法的结果。3.轮询由BeginInvoke返回的IAsyncResult,IAsyncResult.IsCompeted确定异步调用何时完成,然后调用EndInvoke。此处理个人认为与相同。4.将用于回调方法的委托传递给BeginInvoke。该方法在异步调用完成后在ThreadPool线程上执行,它可以调用EndInvoke。这是在强制装换回调函数里面IAsyncResult.AsyncState(BeginInvoke方法的最后一个参数)成委托,然后用委托执行EndInvoke。警告始终在异步调用完成后调用EndInvoke。以上有不理解的稍后可以再理解。例子1)先来个简单的没有回调函数的异步方法例子请再运行程序的时候,仔细看注释,对理解很有帮助。还有,若将注释的中的两个方法都同步,你会发现异步运行的速度优越性。usingSystem;namespaceConsoleApplication1{classClass1{//声明委托publicdelegatevoidAsyncEventHandler();//异步方法voidEvent1(){Console.WriteLine(Event1Start);System.Threading.Thread.Sleep(4000);Console.WriteLine(Event1End);}//同步方法voidEvent2(){Console.WriteLine(Event2Start);inti=1;while(i1000){i=i+1;Console.WriteLine(Event2+i.ToString());}Console.WriteLine(Event2End);}[STAThread]staticvoidMain(string[]args){longstart=0;longend=0;Class1c=newClass1();Console.WriteLine(ready);start=DateTime.Now.Ticks;//实例委托AsyncEventHandlerasy=newAsyncEventHandler(c.Event1);//异步调用开始,没有回调函数和AsyncState,都为nullIAsyncResultia=asy.BeginInvoke(null,null);//同步开始,c.Event2();//异步结束,若没有结束,一直阻塞到调用完成,在此返回该函数的return,若有返回值。asy.EndInvoke(ia);//都同步的情况。//c.Event1();//c.Event2();end=DateTime.Now.Ticks;Console.WriteLine(时间刻度差=+Convert.ToString(end-start));Console.ReadLine();}}}2)下面看有回调函数的WebRequest和WebResponse的异步操作。usingSystem;usingSystem.Net;usingSystem.Threading;usingSystem.Text;usingSystem.IO;//RequestState类用于通过//异步调用传递数据publicclassRequestState{constintBUFFER_SIZE=1024;publicStringBuilderRequestData;publicbyte[]BufferRead;publicHttpWebRequestRequest;publicStreamResponseStream;//创建适当编码类型的解码器publicDecoderStreamDecode=Encoding.UTF8.GetDecoder();publicRequestState(){BufferRead=newbyte[BUFFER_SIZE];RequestData=newStringBuilder();Request=null;ResponseStream=null;}}//ClientGetAsync发出异步请求classClientGetAsync{publicstaticManualResetEventallDone=newManualResetEvent(false);constintBUFFER_SIZE=1024;publicstaticvoidMain(string[]args){if(args.Length1){showusage();return;}//从命令行获取URIUriHttpSite=newUri(args[0]);//创建请求对象HttpWebRequestwreq=(HttpWebRequest)WebRequest.Create(HttpSite);//创建状态对象RequestStaters=newRequestState();//将请求添加到状态,以便它可以被来回传递rs.Request=wreq;//发出异步请求IAsyncResultr=(IAsyncResult)wreq.BeginGetResponse(newAsyncCallback(RespCallback),rs);//将ManualResetEvent设置为Wait,//以便在调用回调前,应用程序不退出allDone.WaitOne();}publicstaticvoidshowusage(){Console.WriteLine(尝试获取(GET)一个URL);Console.WriteLine(\r\n用法::);Console.WriteLine(ClientGetAsyncURL);Console.WriteLine(示例::);Console.WriteLine(ClientGetAsync);}privatestaticvoidRespCallback(IAsyncResultar){//从异步结果获取RequestState对象RequestStaters=(RequestState)ar.AsyncState;//从RequestState获取HttpWebRequestHttpWebRequestreq=rs.Request;//调用EndGetResponse生成HttpWebResponse对象//该对象来自上面发出的请求HttpWebResponseresp=(HttpWebResponse)req.EndGetResponse(ar);//既然我们拥有了响应,就该从//响应流开始读取数据了StreamResponseStream=resp.GetResponseStream();//该读取操作也使用异步完成,所以我们//将要以RequestState存储流rs.ResponseStream=ResponseStream;//请注意,rs.BufferRead被传入到BeginRead。//这是数据将被读入的位置。IAsyncResultiarRead=ResponseStream.BeginRead(rs.BufferRead,0,BUFFER_SIZE,newAsyncCallback(ReadCallBack),rs);}privatestaticvoidReadCallBack(IAsyncResultasyncResult){//从asyncresult获取RequestState对象RequestStaters=(RequestState)asyncResult.AsyncState;//取出在RespCallback中设置的ResponseStreamStreamresponseStream=rs.ResponseStream;//此时rs.BufferRead中应该有一些数据。//读取操作将告诉我们那里是否有数据intread=responseStream.EndRead(asyncResult);if(read0){//准备Char数组缓冲区,用于向Unicode转换Char[]charBuffer=newChar[BUFFER_SIZE];//将字节流转换为Char数组,然后转换为字符串//len显示多少字符被转换为Unicodeintlen=rs.StreamDecode.GetChars(rs.BufferRead,0,read,charBuffer,0);Stringstr=newString(charBuffer,0,len);//将最近读取的数据追加到RequestDatastringbuilder对象中,//该对象包含在RequestState中rs.RequestData.Append(str);//现在发出另一个异步调用,读取更多的数据//请注意,将不断调用此过程,直到//responseStream.EndRead返回-1IAsyncResultar=responseStream.BeginRead(rs.BufferRead,0,BUFFER_SIZE,newAsyncCallback(ReadCallBack),rs);}else{if(rs.RequestData.Length1){//所有数据都已被读取,因此将其显示到控制台stringstrContent;strContent=rs.RequestData.ToString();Console.WriteLine(strContent);}//关闭响应流responseStream.Close();//设置ManualResetEvent,以便主线程可以退出allDone.Set();}return;}}在这里有回调函数,且异步回调中又有异步操作。首先是异步获得ResponseStream,然后异步读取数据。这个程序非常经典。从中可

1 / 14
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功