在.NET中的线程处理(3)

原创 2002年04月22日 09:38:00

使用异步 I/O 完成事件,线程池中的线程将只在收到数据时对数据进行处理,一旦处理完数据,该线程就会返回到线程池中。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

若要进行异步 I/O 调用,必须将操作系统 I/O 句柄与线程池相关联,并且必须指定一个回调方法。当 I/O 操作完成后,线程池中的线程将调用该回调方法。

下面的 C# 代码示例说明了一个简单的异步 I/O 操作。

注意 该示例需要 100MB 以上的可用内存。

[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 I/O-bound.

   public static int processImageRepeats = 20;

 

   // Threads must decrement NumImagesToFinish, and protect

   // their access 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;

 

      Stream stream = state.fs;

      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. No async here.

      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){

            lock(WaitObject){

               Monitor.Pulse(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 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

         );

         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

         );

            lock(WaitObject){

            Monitor.Pulse(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 asynchronous I/O");

      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);

 

}

在.NET中的线程处理(4)

Timer  [C#]计时器是使您能够指定要在指定时间调用的委托的轻量对象。线程池中的线程执行等待操作。使用 Timer 类是非常简单的。需要创建一个 Timer(通过将 TimerCallback ...
  • Paul_Ni
  • Paul_Ni
  • 2002年04月22日 09:38
  • 1146

在.NET中的线程处理(6)

使用线程和线程处理创建、管理和销毁托管线程是非常容易的,但如果不了解托管线程和非托管线程之间的关系以及 ThreadAbortException,则这样做可能会导致预料不到的副作用。创建线程  [C#...
  • Paul_Ni
  • Paul_Ni
  • 2002年04月22日 09:38
  • 2670

在.NET中的线程处理(5)

Mutex  [C#]可以使用 Mutex 对象在线程之间以及跨进程进行同步。虽然 Mutex 不具备 Monitor 类的所有等待和脉冲功能,但它的确提供了创建可在进程之间使用的命名的互斥体的功能。...
  • Paul_Ni
  • Paul_Ni
  • 2002年04月22日 09:38
  • 1290

在.NET中的线程处理(1)

无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作。要使应用程序能够快速响应用户操作,同时在用户事件之间或...
  • Paul_Ni
  • Paul_Ni
  • 2002年04月22日 09:39
  • 1811

在.NET中的线程处理(2)

.NET 框架提供了许多有助于您创建和管理多线程应用程序的对象。WaitHandle 对象可以帮助您响应其他线程执行的操作,尤其是在与非托管代码交互操作时。ThreadPool 为大多数任务提供最佳的...
  • Paul_Ni
  • Paul_Ni
  • 2002年04月22日 09:39
  • 1284

.net 线程处理 托管线程处理的最佳做法

托管线程处理的最佳做法 发送反馈 多线程编程需要在编程时倍加注意。对于多数任务,通过将执行请求以线程池线程的方式排队,可以降低复杂性。本主题将探讨更复杂...
  • wuhenzhangxing
  • wuhenzhangxing
  • 2015年01月13日 11:40
  • 637

GoogleNet家族

一、GoogLeNet相关论文及下载地址 [v1] Going Deeper withConvolutions, 6.67% test error,2014.9 论文地址:http://arxiv...
  • Touch_Dream
  • Touch_Dream
  • 2017年08月23日 09:59
  • 352

Android中的线程处理

注:本文来自CSDN博主的一篇文章,个人觉得写得很好,值得借鉴,故收录在此 Android进程模型 在安装Android应用程序的时候,Android会为每个程序分配一个Lin...
  • DLUTBruceZhang
  • DLUTBruceZhang
  • 2013年02月09日 17:59
  • 2398

.net使用线程与线程处理

1.线程的创建   .net是通过Thread类来描述线程的,线程的创建即构造Thread类即可。    Thread常用的构造函数有两个,分别是:   Thread(ThreadStart)  与 ...
  • peakwu
  • peakwu
  • 2008年10月26日 21:19
  • 421

线程处理

  • zgqtxwd
  • zgqtxwd
  • 2008年04月24日 17:06
  • 136
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在.NET中的线程处理(3)
举报原因:
原因补充:

(最多只允许输入30个字)