Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when you await a synchronous method

If I have a synchronous method "GetStrings()":

private static Task<string[]> GetStrings(IEnumerable<int> ids)
{
    var tasks = ids.Distinct().Select(GetString);
    return Task.WhenAll(tasks);
}

private static async Task<string> GetString(int stringId)
{
    await Task.Delay(15000);
    return "hello" + stringId;
}

(which itself calls async method "GetString()")

And I call this synchronous "GetStrings()" method from an async method:

public static async Task Main()
{
    var ids = new List<int> { 1, 2, 3 };
    await GetStrings(ids);
    Console.WriteLine("all done");
    Console.ReadLine();
}

What would be the behavioural difference, if GetStrings() was actually async? (and performed an await on the Task.WhenAll)

Would it simply stop Task.WhenAll from blocking the thread? I've found some production code which looks like this, so I've put together this small example to try and understand what's going. It's difficult to identify the difference though.

like image 336
FBryant87 Avatar asked Feb 21 '18 10:02

FBryant87


People also ask

Can you use await on a synchronous function?

Async/await helps you write synchronous-looking JavaScript code that works asynchronously. Await is in an async function to ensure that all promises that are returned in the function are synchronized.

What happens when we use await?

The await expression causes async function execution to pause until a promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment. When resumed, the value of the await expression is that of the fulfilled promise.

What happens if we execute an asynchronous method but don't await it?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.

Is await synchronous or asynchronous?

Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.


1 Answers

Task.WhenAll doesn't block anyway, unlike Task.WaitAll. It just return a task that completes when all of the original tasks have completed.

It's important to understand that you don't await a method - you await a value (or some type that has to be awaitable). The await mechanism doesn't care how you obtained that value.

If GetStrings were async, there'd be one important difference: any exceptions thrown (e.g. if ids were null) would be result in a faulted task, whereas currently the exception would be thrown directly.

like image 181
Jon Skeet Avatar answered Oct 26 '22 16:10

Jon Skeet