使用 .NET的IO(2) Paul_Ni(原作)(补充)

发表于:2007-06-30来源:作者:点击数: 标签:
[C#]using System;using System.IO;using System.Threading;using System.Runtime.InteropServices; public class BulkImageProcAsync{public const String ImageBaseName = tmpImage-;public const int numImages = 200;public const int numPixels = 512*51
[C#]using System;using System.IO;using System.Threading;using System.Runtime.InteropServices; 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 you can vary the number// of times you repeat that loop to make the application more CPU-bound// or more IO-bound.public static int processImageRepeats = 20; // Threads must decrement NumImagesToFinish, and protect// their aclearcase/" target="_blank" >ccess to it through 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];public class ImageStateObject{public byte[] pixels;public int imageNum;public FileStream fs;} 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.Handle);   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" :       "asynchronously"));Stream stream = state.fs;//(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); ProcessImage(state.pixels, state.imageNum);stream.Close(); // Now write out the image.  // Using asynchronous IO here appears not to be best practice.  It ends up// swamping the threadpool, since the threadpool threads are blocked // on IO requests that we@#ve just queued to the threadpool. FileStream fs = new FileStream(ImageBaseName+state.imageNum+".done",    FileMode.Create, FileAccess.Write, FileShare.None, 4096, false);fs.Write(state.pixels, 0, numPixels);fs.Close(); // This application model uses too much memory.// Releasing memory as soon as possible is a good idea, especially global// state.state.pixels = null; // Record that an image is done now.lock(NumImagesMutex) {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<processImageRepeats; i++)   for(int j=0; j<numPixels; j++)      pixels[j] += 1; Console.WriteLine("ProcessImage "+imageNum+" done.");} public static void ProcessImagesInBulk(){Console.WriteLine("Processing images...  ");long t0 = Environment.TickCount;NumImagesToFinish = numImages;AsyncCallback readImageCallback = new AsyncCallback(ReadInImageCallback);   for(int i=0; i<numImages; i++)    {      ImageStateObject state = new ImageStateObject();      state.pixels = new byte[numPixels];      state.imageNum = i;      // Very large items are read only once, so you can make the       // buffer on the file stream very small to save memory.      FileStream fs = new FileStream(ImageBaseName+i+".tmp",          FileMode.Open, FileAccess.Read, FileShare.Read, 1, true);      state.fs = fs;      fs.BeginRead(state.pixels, 0, numPixels, readImageCallback, state);   } // Determine whether all images are done being processed.  // 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);} long t1 = Environment.TickCount;Console.WriteLine("Total time processing images: {0} ms", (t1-t0));} 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  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          async IO");      Console.WriteLine("Simulates applying a simple transformation to          "+numImages+" "images"");      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();      ProcessImagesInBulk();      Cleanup();   }   [DllImport("KERNEL32", SetLastError=true)]   private static extern void FlushFileBuffers(IntPtr handle);}

以下是同一假设的同步示例。[C#]using System;using System.IO;using System.Threading;using System.Runtime.InteropServices; 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 you can vary the number// of times you repeat that loop to make the application more CPU-bound or// more IO-bound.public static int processImageRepeats = 20; 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.Handle);fs.Close();}Console.WriteLine("Done.");} public static void ProcessImage(byte[] pixels, int imageNum){Console.WriteLine("ProcessImage "+imageNum); // Do some CPU-intensive operation on the imagefor(int i=0; i<processImageRepeats; i++)for(int j=0; j<numPixels; j++)pixels[j] += 1; Console.WriteLine("ProcessImage "+imageNum+" done.");} public static void ProcessImagesInBulk(){Console.WriteLine("Processing images...  ");long t0 = Environment.TickCount; 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();} long t1 = Environment.TickCount;Console.WriteLine("Total time processing images: {0} ms", (t1-t0));} 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(){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 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)]private static extern void FlushFileBuffers(IntPtr handle);}

原文转自:http://www.ltesting.net