Asynchronous File I/O
Synchronous I/O means that the method is blocked until the I/O operation is complete, and then the method returns its data. With asynchronous I/O, a user can call BeginRead. The main thread can continue doing other work, and later the user will be able to process the data. Also, multiple I/O requests can be pending simultaneously.
To be informed when this data is available, you can call EndRead or EndWrite passing in the IAsyncResult corresponding to the I/O request you issued. You can also provide a callback method that should call EndRead or EndWrite to figure out how many bytes were read or written. Asynchronous I/O can offer better performance when many I/O requests are pending simultaneously, but generally requires some significant restructuring of your application to work correctly.
The Stream class supports the mixing of synchronous and asynchronous reads and writes on the same stream, regardless of whether the operating system allows this. Stream provides default implementations of asynchronous read and write operations in terms of their synchronous implementations, and provides default implementations of synchronous read and write operations in terms of their asynchronous implementations.
When implementing a class derived from Stream, it is necessary to provide an implementation for either the synchronous or the asynchronous Read and Write methods. While overriding Read and Write is permissible, and the default implementations of the asynchronous methods (BeginRead, EndRead, BeginWrite, and EndWrite) will work with your implementation of the synchronous methods, this does not provide the most efficient performance. Similarly, the synchronous Read and Write methods will work correctly if you provide an implementation of the asynchronous methods, but performance is generally better if you specifically implement the synchronous methods. The default implementations of ReadByte and WriteByte call the synchronous Read and Write methods with a one-element byte array. When deriving classes from Stream, if you have an internal byte buffer, it is strongly recommended that you override these methods to access your internal buffer for better performance.
A stream that connects to a backing store overrides either the synchronous or asynchronous Read and Write methods to get the functionality of the other by default. If a stream does not support asynchronous or synchronous operations, the implementer need only make the appropriate methods throw exceptions.
The following example is an asynchronous implementation of a hypothetical bulk image processor, followed by a synchronous implementation example. This code is designed to perform a CPU-intensive operation on every file in a directory. For more information, see the Asynchronous Programming Design Patterns topic.
Here is a synchronous example of the same idea.