I am trying to understand what exactly, in C#, a method using async await
is doing under the hood.
Consider the following two examples:
static async Task<byte[]> MyReadAsync1(Stream source)
{
var result = new byte[1024];
int readBytes = 0;
while (readBytes != result.Length)
{
int singleRead = await source.ReadAsync(result, readBytes, result.Length - readBytes);
if (singleRead == 0)
break;
readBytes += singleRead;
}
if (readBytes == result.Length)
return result;
return result.Take(readBytes).ToArray();
}
static Task<byte[]> MyReadAsync2(Stream source)
{
return Task.Run(() =>
{
var result = new byte[1024];
int readBytes = 0;
while (readBytes != result.Length)
{
int singleRead;
try
{
singleRead = source.ReadAsync(result, readBytes, result.Length - readBytes).Result;
}
catch (AggregateException e)
{
ExceptionDispatchInfo.Capture(e.InnerException).Throw();
}
if (singleRead == 0)
break;
readBytes += singleRead;
}
if (readBytes == result.Length)
return result;
return result.Take(readBytes).ToArray();
});
}
My question is: Are these two methods equivalent?
If I execute them, it looks like they are. Neither of them is blocking the calling thread. They are doing the exact same thing as far as I can tell, even in case of any exceptions being thrown.
If they really are equivalent, does the compiler produce the same code? Would that mean that async await
does nothing else but save me type some boilerplate code, starting a task and unwrapping AggregateExceptions?
If there is a difference, what exactly is it and would it be possible to achieve the exact same behavior without async await
?
Note: I've seen the question What is the purpose of “return await” in C#? and I understand the answers given there. But that covers only the case of one single return statement, whereas my question is meant to be more general.
I'm not questioning the purpose of async await
, I just want to understand it in detail.
Update
The possible duplicate does not answer my question. That question only covers a one single line of code, comparing .Result
and await
. In my question I have many lines of additional code that are "mixed" with asynchronous code and in MyReadAsync2
method I'm wrapping the entire execution in Task.Run
. I cannot see how the other question addresses any of these additional questions.