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.
CreateHugeFile This is needed for testing. Make sure you have a correct path here—you can change it as needed for your system.
Async 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.
C# program that uses async, StreamReader ReadToEndAsync
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:
805Notes, 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.
Results 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.