StreamReader ReadToEndAsync Example
This page was last reviewed on Dec 6, 2022.
Dot Net Perls
StreamReader, ReadToEndAsync. With ReadToEndAsync on StreamReader, we can read in a file without blocking other code execution. But when can this feature lead to a performance gain?
In this test, we perform an expensive, CPU-bound computation while reading in a file. The same computation is done in the Main method.
Example code. Here we have 2 code paths: the first uses async and await. The second does not. The code does the same things, but the first iteration in the loop is asynchronous.
Info The file is needed for testing. Make sure you have a correct path here—you can change it as needed for your system.
Next Consider ComputeDataFromFileAsync. It uses Task, async, await, and ReadToEndAsync on StreamReader.
And Both Compute Data methods use calls to ComputeSum(). This causes extreme CPU load.
using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; class Program { const string _file = @"C:\programs\huge-file"; public static void Main() { // Huge file needed for testing. CreateHugeFile(); // Loop over tests. for (int i = 0; i <= 1; i++) { // Use async on first iteration only. bool useAsync = i == 0; Console.WriteLine("Use async: " + useAsync); var t1 = Stopwatch.StartNew(); if (useAsync) { // Use async code here. Task<int> task = ComputeDataFromFileAsync(); Console.WriteLine(ComputeSum()); task.Wait(); Console.WriteLine("Data: " + task.Result); } else { // Use synchronous code here. int result = ComputeDataFromFile(); Console.WriteLine(ComputeSum()); Console.WriteLine("Data: " + result); } Console.WriteLine("Elapsed: " + t1.ElapsedMilliseconds.ToString()); } } static void CreateHugeFile() { using (StreamWriter writer = new StreamWriter(_file)) { for (int i = 0; i < 10000; i++) { writer.WriteLine("Huge file line"); } } } static double ComputeSum(int lengthArgument = 60000) { // Does many computations based on argument. // ... Meant to be slow. double[] array = new double[lengthArgument]; for (int i = 0; i < array.Length; i++) { array[i] = i; } for (int z = 0; z < 100; z++) { for (int i = 0; i < array.Length; i++) { array[i] = (int)Math.Sqrt(array[i]) + (int)Math.Pow(array[i], 2) + 10; } } return array.Sum(); } static async Task<int> ComputeDataFromFileAsync() { int count = 0; using (StreamReader reader = new StreamReader(_file)) { string contents = await reader.ReadToEndAsync(); count += (int)ComputeSum(contents.Length % 60000); } return count; } static int ComputeDataFromFile() { int count = 0; using (StreamReader reader = new StreamReader(_file)) { string contents = reader.ReadToEnd(); count += (int)ComputeSum(contents.Length % 60000); } return count; } }
Use async: True 2230342492166 Data: -2147483648 Elapsed: 522 Use async: False 2230342492166 Data: -2147483648 Elapsed: 805
Notes, ComputeSum. With ComputeSum, we have high CPU usage during file loads. And we call ComputeSum in main as well—this is where the performance is most affected by a sync code.
Result With ReadToEndAsync, our program finishes in 522 ms. With ReadToEnd (no async) it finishes in 805 ms.
So The async, await, Task, and ReadToEndAsync features lead to a significant speedup in the program.
Notes, results. The programs come to the same result—they do the same thing. But async gives us parallel processing, so the program finishes much faster.
A summary. With async, await, ReadToEndAsync and Task, we can achieve a big performance boost. The important thing is that excess CPU usage must be present for this to help.
StreamReader ReadToEnd
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
No updates found for this page.
© 2007-2024 Sam Allen.