Take advantage of the async and await keywords in C# to implement asynchronous file operations You can take advantage of asynchrony to perform resource-intensive I/O operations sans the need to block the main or the executing thread of the application. Asynchrony when used properly can increase the responsiveness and scalability of your applications to a considerable extent. This article presents an overview on asynchronous file operations using C#. Why is asynchrony needed? Asynchronous programming enables you to execute tasks separate from the main application thread, then notifies the thread when its execution is over. Asynchrony helps you execute tasks sans the need of holding up the execution flow or responsiveness of your application. You can leverage asynchrony to improve the performance and responsiveness of your application as the calling thread can continue to perform other operations while the method that can been called asynchronously continues to execute. The async and await keywords If you were to use .Net Framework and its earlier versions, you could leverage the BeginRead() and the EndRead() methods to implement asynchronous operations when working with files. Although these methods are still available as part of the newer versions of the .Net Framework, you can use the two new keywords async and await that have been introduced as part of .Net Framework 4.5. Hence, you can take advantage of async and await to implement asynchronous file operations when working with .Net Framework 4.5 or later. You can learn more about async and await on MSDN. In using asynchrony you can make the user interface threads more responsive and perform other activities while the asynchronous operation is in progress. Performing asynchronous file operations You can use the FileStream class to perform asynchronous I/O operations. In most cases, this would ensure that the calling thread is not blocked while the asynchronous file operation is in progress. To use this option, you should turn on the asynchronous option (with the option useAsync: true) when creating an instance of the FileStream class. This is shown in the code snippet given below. FileStream fileStream = new FileStream("C:IDG.txt", FileMode.Append, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true); The following method writes a text passed to it as parameter to a file asynchronously. Note the usage of the await keyword when calling the WriteAsync() method and the async keyword that is used in the method signature to imply this method would have one or more await statements. static async Task WriteToFileAsync(string filePath, string text) { if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); if (string.IsNullOrEmpty(text)) throw new ArgumentNullException("text"); byte[] buffer = Encoding.Unicode.GetBytes(text); Int32 offset = 0; Int32 sizeOfBuffer = 4096; FileStream fileStream = null; try { fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.None, bufferSize: sizeOfBuffer, useAsync: true); await fileStream.WriteAsync(buffer, offset, buffer.Length); } catch { //Write code here to handle exceptions. } finally { if(fileStream != null) fileStream.Dispose(); } } It should be noted that if you don’t include the await keyword inside an asynchronous method, the entire method would execute synchronously. Note that the usage of async and await doesn’t create any additional threads. The following code snippet illustrates how you can call the WriteToFileAsync() method from the Main() method to write a text asynchronously. static Task WriteToFile() { string filePath = "C:IDG.txt"; string text = "Hello Worldrn"; return WriteToFileAsync(filePath, text); } static void Main(string[] args) { WriteToFile().Wait(); Console.Write("Press any key to exit... "); Console.ReadKey(); } The following method reads text from a file asynchronously. You would need to pass the file name and the size of the buffer as parameters. Note how the object readBuffer is set to null in the catch block if an exception occurs so that the caller method can identify if an exception has occurred while attempting to read text from the file. static async Task<string> ReadFromFileAsync(string filePath, int bufferSize) { if (bufferSize < 1024) throw new ArgumentNullException("bufferSize"); if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); StringBuilder readBuffer = null; byte[] buffer = new byte[bufferSize]; FileStream fileStream = null; try { readBuffer = new StringBuilder(); fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: bufferSize, useAsync: true); Int32 bytesRead = 0; while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { readBuffer.Append(Encoding.Unicode.GetString(buffer, 0, bytesRead)); } } catch { readBuffer = null; //Write code here to handle exceptions; } finally { if (fileStream != null) fileStream.Dispose(); } return readBuffer.ToString(); } Note that we have used the FileStream class in the code examples presented in this post as StreamReader and StreamWriter doesn’t provide support for asynchronous read and write operations. You can invoke the ReadFromFileAsync() method from the following method. Note that the ReadFromFile() method given below returns a Task<string> object. static async Task<string> ReadFromFile() { string filePath = "C:IDG.txt"; return await ReadFromFileAsync(filePath, 4096); } You can now call the ReadFromFile() method from the Main() method to retrieve and display all text from the file in the console window. <span style="line-height: 1.75em;">static void Main(string[] args)</span> { string text = ReadFromFile().Result; Console.Write(text); Console.ReadKey(); } Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos