C# .NET Stream.BeginRead() is blocking, not parallel thread

Posted on 2009-04-19
Last Modified: 2013-11-07
I am using C#.NET 1.1, however it would appear that my problem may be with any release of the .NET Famework (so, 2.0 also, as I think 3.0 and 3.5 use the same base library as 2.0).

My problem is that when I issue a simple BeginRead() off of a Stream variable (in System.IO), the method blocks until the entire file is read.  The arguments for BeginRead are in the code block below.  I pass in my byte[] buffer, an offset of 0, the length of my buffer, my callback method, and in this case I'm using null for object state, which is perfectly valid.    It _does_ read, so it works, it just doesn't continue on as it's supposed to.

If I call BeginRead off my Stream var and then immediately issue a Console.WriteLine("This line right after BeginRead call!!"), I don''t receive the Console.WriteLine until -after- the entire read process has completed.  I've tried this with changing the size of the byte buffer and the size of the file, I've even put the file on an external drive and given a buffer length of like 1 but to no avail.  Actually with a large file (~200MB) and a byte buffer length of 1 I get a Fatal Stack Overflow error and the program throws.

Simple C# program.  Ideas?  Am I misunderstanding the idea of BeginRead's state object here, or what is going on?  I've done a bit of digging and this does appear to be the appropriate use.  Also I've encountered training documentation which says not only that this is the way to do it but also that until you issue an EndRead(), you won't get a block (EndRead() apparently blocks until the file is done reading, but I wouldn't know as my BeginRead() is blocking).  One other interesting thing to note is that I get multiple calls to my callback method.  Help!

// Signature for BeginRead()

public virtual IAsyncResult BeginRead(

   byte[] buffer,

   int offset,

   int count,

   AsyncCallback callback,

   object state


Open in new window

Question by:coder1313514512456
    LVL 9

    Expert Comment

    OK.. First.. where to you put the line EndRead ? It should be in your callback method. Isn't it ? If so, you should set a buffer around 4000, which tells the reader to read 4000 bytes at a time.

    So, if you have a file of 40000 bytes, your callback method will be called with a 4000 bytes array (the first ones). The callback method shall have the EndRead as first call into the method. Then looking if the buffer return is not empty, you call again the BeginRead, or if it is, you exit the method.

    So, you will have to combines to bytes into a Collection, and when finished, you will have to whole file read. This should gives you an Asynchronous way to read the file. Although, I never read a file asynchronously, I just use this with NetworkStream, it should work. If not, give me the code where all BeginRead and EndRead are located. (The whole methods).

    Author Comment

    Sure.  Since it's pretty compact, here it is:

    // aioee.cs - Testing Asynchronous I/O  -  EE ask version
    using System;
    using System.IO;
    using System.Text;
    using System.Threading;
    namespace AIOEE
    	public class AsyncTest
    		// private const int bufferSize = 10;           // to try to slow it down
    		private const int bufferSize = 256;             // arbitrary
    		// private const int bufferSize = 4000;         // suggested by djon2003
    		// private const int bufferSize = 1000000000;   // fast, of course
    		private const string inputFileName = "somefile.txt";
    		private byte[] buffer;
    		private Stream inStream;
    		private AsyncCallback callbackMethod;
    		public AsyncTest()
    			inStream = File.OpenRead(inputFileName);
    			buffer = new byte[bufferSize];
    			callbackMethod = new AsyncCallback(this.OnCompletedRead);
    		}  // end AsyncTest()  ctor
    		public static void Main(string[] args)
    			AsyncTest tester = new AsyncTest();
    		} // end Main()
    		public void Run(string[] args)
    			// using null instead of a local state object
    			inStream.BeginRead(buffer, 0, buffer.Length, callbackMethod, null);
    			Console.WriteLine("Run():  Immediately following BeginRead() call.");
    			// do some token work in between to prove that we're asynchronous.
    			// Note that this never shows up until the end regardless of file/buffer sizes,
    			// which means the BeginRead() is blocking.
    			for (long i=0; i<=100000; i++)
    				if (i%1000 == 0)
    					Console.WriteLine("i:  {0}", i);
    				}  // end if
    			}  // end for
    		} // end Run()
    		// Callback method.
    		void OnCompletedRead(IAsyncResult asyncResult)
    			Console.WriteLine("HIT ONCOMPLETEDREAD Method.");
    			int bytesRead = inStream.EndRead(asyncResult);
    			if (bytesRead == 0)
    				Console.WriteLine("OnCompletedRead():  No bytes read -- must be done");
    				string s = Encoding.ASCII.GetString(buffer, 0, bytesRead);
    				// my this could get large
    				// Console.WriteLine(s);
    				// If bytes have been read, try to read more
    				// Is this why I'm blocking?
    				// Is this also why I'm bombing on large files with small buffer sizes?
    				inStream.BeginRead(buffer, 0, buffer.Length, callbackMethod, null);
    			}  // end if-else
    		}  // end OnCompletedRead()
    	}  // end class AsyncTest
    } // end namespace AIOEE

    Open in new window


    Author Comment

    Oh, and correction to Run() method:

    void Run()
       // ...

    Open in new window


    Accepted Solution

    Solved it -- it's because I was using 1.1 insted of 2.0.
    This was a problem in 1.1 and I totally forgot about it.
    I am such an idiot!  Thanks for the help.
    LVL 9

    Expert Comment

    Good thing you find your way !

    Featured Post

    Find Ransomware Secrets With All-Source Analysis

    Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

    Join & Write a Comment

    This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
    Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
    This video is in connection to the article "The case of a missing mobile phone (". It will help one to understand clearly the steps to track a lost android phone.
    Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

    731 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now