先来说说同步和异步操作之间的主要区别。在同步I/O操作中,方法将一直处于等待状态,直到I/O操作完成。而在异步I/O操作中,在开始了I/O操作后,程序的方法可以转移去执行其它的操作,这样大大提高了程序执行的效率。
由于Windows是一个多任务的操作系统,在同一时刻系统可能会接受到多个I/O操作请求,要求对磁盘文件执行各种操作。如果采用同步方式,那么每时每刻最多只能有一个I/O操作在进行,而其它的任务都处于等待状态,系统的利用率将会大为降低。异步I/O操作则较好地解决了这种性能上的问题。
Stream类支持在同一个流中既可以进行同步读写,也可以进行异步读写。Stream类是一个抽象类,它为我们提供了BeginRead、BeginWrite、EndReader、EndWrite、Read、Write、Seek等成员方法,协同完成对流的读写操作。所有这些方法都是虚方法。因此,在我们自己设计Stream类的派生类时,我们在类用于读写的成员方法Read和Write中应该重载这些方法,并同时设计它们同步和异步的执行代码。BeginRead,EndRead,BeginWrite和EndWrite方法默认为我们提供的是异步读写操作方式,如果你的派生类的Read和Write方法执行同步操作时,那么程序提供的效率不会很好。只有当它们执行异步操作时,我们才能有效地提高程序的执行效率。
Stream类还提供了ReadByte和WriteByte方法,用于一次读写方式,这时我们就需要编写自己的方法来抛出一个异常。
下面的代码是在.NET联机帮助中提供的一个异步读写操作的例子,程序模拟了一个多处理器系统的工作。
程序清单17-8:
using System; using System.IO; using System.Threading; using BenchUtil; public class BulkImageProcAsync{ public const String ImageBaseName="tmpImage-"; public const int numImages=200; public const int numPixels=512*512; //ProcessImage has a simple O(N)loop,and we can vary the number //of times we repeat that loop to make the app more CPU-bound or more IO-bound. public static int processImageRepeats=20; //Threads must decrement NumImagesToFinish,and protect //their access to it via a mutex. public static int NumImagesToFinish=numImages; public static Object NumImagesMutex=new Object[0]; //WaitObject is signalled when all image processing is done. public static Object WaitObject=new Object[0]; internal static PerfTimer Pf=new PerfTimer("Asynchronous Bulk Image Processor"); public class ImageStateObject{ public byte[] pixels; public int imageNum; } public static void MakeImageFiles(){ int sides=(int)Math.Sqrt(numPixels); Console.Write("Making"+numImages+""+sides+"x"+sides+"images... "); byte[] pixels=new byte[numPixels]; for(int i=0;i<numPixels;i++) pixels[i]=(byte)i; for(int i=0;i<numImages;i++){ FileStream fs=new FileStream(ImageBaseName+i+ ".tmp",FileMode.Create,FileAccess.Write,FileShare.None,8192,false); fs.Write(pixes,0,pixels.Length); FlushFileBuffers(fs.GetHandle()); fs.Close(); } Console.WriteLine("Done."); } public static void ReadInImageCallback(IAsyncResult asyncResult){ ImageStateObject state=(ImageStateObject)asyncResult.AsyncState; Console.WriteLine("Image"+state.imageNum+"was read. "+(asyncResult.CompletedSynchronously?"synchronously":"asyncchronously")); Stream stream=(Stream)asyncResult.AsyncObject; int bytesRead=stream.EndRead(asyncResult); if(bytesRead!=numPixels) throw new Exception("In ReadInImageCallback,got wrong number of bytes from the image! got:"+bytesRead); ProcessImages(state.pixels,state.imageNum); stream.Close(); //Now write out the image. //using async IO here probably swamps the threadpool,since //there are blocked threadpool threads on soon-to-be-//spawned //threadpool threads FileStream fs=new FileStream(ImageBaseName+state.imageNum+".done", FileMode.Create,FileAccess.Write,FileShare.None,4096,false); fs.Write(state.pixels,0,numPixels); //IAsyncResult writeResult=fs.BeginWrtie(state.pixels, //0,numPixels,null,null); //fs.EndWrite(writeResult); fs.Close(); //Release memory as soon as possible,especially global state. state.pixels=null; //Record that an image is done now. lock(NumImageMutex){ NumImagesToFinish--; if(NumImagesToFinish==0){ Monitor.Enter(WaitObject); Monitor.Pulse(WaitObject); Monitor.Exit(WaitObject); } } } public static void ProcessImage(byte[] pixels,int imageNum){ //Console.WriteLine("ProcessImage"+imageNum); //Do some CPU-intensive operation on the image. for(int i=0;i<processImageReports;i++) for(int j=0;j<numPixels;j++) pixels[j]+=1; //Console.WriteLine("ProcessImage"+imageNum+"done."); } public static void ProcessImagesInBulk(){ Console.WriteLine("Processing images..."); //int timer=Pf.StartTimer("ProcessImages"); int timer=Pf.StartTimer("Total Time"); NumImagesToFinish=numImages; AsyncCallback readImagesCallback=new AsyncCallback(ReadInImageCallback); for(int i=0;i<numImages;i++){ ImageStateObject state=new ImageStateObject(); state.pixels=new byte[numPixels]; state.imageNum=i; //Because very large items are read only once,the buffer //on the file stream can be very small to save memory. FileStream fs=new FileStream(ImageBaseName+i+".tmp",FileMode.Open, FileAccess.Read,FileShare.Read,1,true); fs.BeginRead(state.pixels,0,numPixels,readImageCallback,state); } //Ensure all image processing is done. //If not,block until all are finished. bool mustBlock=false; lock(NumImagesMutex) if(NumImagesToFinish>0) mustBlock=true; } if(mustBlock){ Console.WriteLine("All worker threads are queued...Blocking until they complete. numLeft:"+NumImagesToFinish); Monitor.Enter(WaitObject); Monitor.Wait(WaitObject); Monitor.Exit(WaitObject); } Pf.StopTimer(timer); Pf.OutputStoppedTime(); } public static void Cleanup(){ for(int i=0;i<numImages;i++){ File.Delete(ImageBaseName+i+".tmp"); File.Delete(ImageBaseName+i+".done"); } } public static void TryToClearDiskCache(){ //Try to force all pending writes to disk,AND to clear the //disk cache of any data. byte[] bytes=new byte[100*(1<<20)]; for(int i=0;i<bytes.Length;i++) bytes[i]=0; bytes=null; GC.Collect(); Thread.Sleep(2000); } public static void Main(String[] args){ Console.WriteLine("Bulk image processing sample application,using asycn IO"); Console.WriteLine("Simulates applying a simple transformation to "+numImages+" \"imgaes\""); Console.WriteLine("ie,Async FileStream & Threadpool benchmark)"); Console.Writeline("Warning - this test requires"+(numPixels*numImages*2)+" bytes of tmp space"); if(args.length==1){ processImageRepeats=Int32.Parse(args[0]); Console.WriteLine("ProcessImage inner loop - "+processImageRepeats); } MakeImageFiles(); TryToClearDiskCache(); ProcessImageInBulk(); Cleanup(); } [dllimport("KERNEL32",SetlastError=true)] static extern void FlushFileBuffers(int handle); } 这里是采用同步方法实现同样功能的程序。 程序清单17-9: using System; using System.IO; using System.Threading; using BenchUtil; public class BulkImageProcSync { public const String ImageBaseName="tmpImage-"; public const int numImages=200; public const int numPixels=512*512; //ProcessImage has a simple O(N) loop,and we can vary the number //of times we repeat that loop to make the app more CPU-bound or more IO-bound. public static int processImageRepeats=20; internal static PerfTimer Pf=new PerfTimer("Synchronous Bulk Image Processor"); public static void MakeImageFiles(){ int sides=(int)Math.Sqrt(numPixels); Console.Write("Making"+numImages+""+sides+"x"+sides+"images... "); byte[] pixels=new byte[numPixels]; for(int i=0;i<numPixels;i++) pixels[i]=(byte)i; for(int i=0;i<numImages;i++){ FileStream fs=new FileStream(ImageBaseName+i+".tmp",FileMode.Create, FileAccess.Write,FileShare.None,8192,false); fs.Write(pixels,0,pixels.Length); FlushFileBuffers(fs.GetHandle()); fs.Close(); } Console.WriteLine("Done."); } public static void ProcessImage(byte[] pixels,int imageNum){ //Console.WriteLine("ProcessImage"+imageNum); //Do some CPU-intensive operation on the image for(int i=0;i<processImageReports;i++) for(int j=0;j<numPixels;j++) pixels[j]+=1; //Console.WriteLine("processImage"+imageNum+"//done."); } public static void ProcessImagesInBulk(){ Console.WriteLine("Processing images..."); int timer=Pf.StartTimer("Total Time"); byte[] pixels=new byte[numPixels]; for(int i=0;i<numImages;i++){ FileStream input=new FileStream(ImageBaseName+i+".tmp", FileMode.Open,FileAccess.Read,FileShare.Read,4196,false); input.Read(pixels,0,numPixels); input:Close(); ProcessImage(pixels,i); FileStream output=new FileStream(ImageBaseName+i+ ".done",FileMode.Create,FileAccess.Write,FileShare.None,4196,false); output.Write(pixels,0,numPixels); output.Close(); } Pf.StopTimer(timer); Pf.OutputStoppedTime(); } public static void Cleanup() { for(int i=0;i<numImages;i++){ File.Delete(ImageBaseName+i+".tmp"); File.Delete(ImageBaseName+i+".done"); } } public static void TryToClearDiskCache(){ bute[] bytes=new byte[100*(1<<20)]; for(int i=0;i<bytes.Length;i++) bytes[i]=0; bytes=null; GC.Collect(); Thread.Sleep(2000); } public static void Main(String[] args){ Console.WriteLine("Bulk image processing sample application,using synchronous IO"); Console.WriteLine("Simulates applying a simple transformation to "+numImages+" \"images\""); Console.WriteLine("ie,Sync FileStream benchmark)"); Console.WriteLine("Warning - this test requires"+(numPixels*numImages*2)+" bytes of tmp space"); if(args.Length==1){ processImageRepeats=Int32.Parse(args[0]); Console.WriteLine("ProcessImage inner loop -"+processImageRepeats); } MakeImageFiles(); TryToClearDiskCache(); ProcessImagesInBulk(); Cleanup(); } [dllimport"KERNEL32",SetlastError=true)] static extern void FlushFileBuffers(int handlw); }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, static
, 方法
, public
, state
, 异步I/O
fs.write方法
c站、c语言、cf、ch、c罗,以便于您获取更多的相关知识。