So far I think I've grasped the concepts of how async await can make your application more responsive but I'm hung up on two points:
Layer Considerations Does async await have to go from the repository layer, all the way up to the MVC or WCF tier to get the performance benefits or can I just do async operations on my repository methods that are taking a long time?
"await" usage If I can just work at the repository level there's one part I don't understand. Using this (low-tier) approach, will the thread be able to service incoming client requests while waiting on the io bound code to finish?
I put together a sample console application, in my mind, while the long running task is continuing, another user could make a request to my web application. Using my little library (to ease integration and exception handling), would their request be serviced by the pending thread or does the voidTask.Wait();
cause the thread to block?
public class AsyncTest
{
public void RunTest()
{
try
{
using (var task = new RunTask(LongRunningTask))
{
Console.WriteLine("Echo two things:");
for (int i = 0; i < 2; i++)
{
var input = Console.ReadLine();
Console.WriteLine(string.Format("Echoing \"{0}\"", input));
}
}
}
catch (Exception e)
{
Console.WriteLine("Error, hm, what happened??");
Console.WriteLine();
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
public void LongRunningTask()
{
var totals = 0;
for (int i = 0; i < 30; i++)
{
Thread.Sleep(1000);
totals += 5;
if (i == 25)
throw new ArgumentException("I can't handle this! Errorr!!@!@");
Console.WriteLine(string.Format("LongRunningTask Step {0}...", (i + 1)));
}
}
}
public class RunTask : IDisposable
{
public delegate void IOBoundOperations();
private Task voidTask;
public RunTask(IOBoundOperations task)
{
voidTask = Execute(task);
}
async public Task Execute(IOBoundOperations task)
{
await Task.Run(() =>
{
task();
});
}
public void Dispose()
{
try
{
voidTask.Wait();
}
catch
{
throw new AsyncException("Failed to run task asynchronously: " +
voidTask.Exception.InnerException.Message, voidTask.Exception.InnerException);
}
}
}
I put in the wait, because I'll need it for tasks that will return data to the calling code that it may depend on. I also did it because I noticed the process won't complete until the thread is done executing my asynchronous stuff as well.
I can find lots of information on async/await and it's benefits, just nothing on this on this one particular aspect.