lele.lic
lele.lic

Reputation: 23

Difference Await and ContinueWith

I've read some threads regards the difference between await and ContinueWith. But no one has answer me completely.

I've got a DataAccess Layer that insert records in a database using Dapper. The InsertAsync method is:

public Task<int> InsertAsync(TEntity entity)
{
return Connection.InsertAsync(entity, Transaction).ContinueWith(r => Convert.ToInt32(r.Result));
}

I don't use async and await because in my head who will use this method will waiting for the result. Is correct?

Upvotes: 0

Views: 801

Answers (3)

Flater
Flater

Reputation: 13783

I don't use async and await because in my head who will use this method will waiting for the result. Is correct?

That is not correct. While the await keyword does indeed wait for Connection.InsertAsync to complete before it calls Convert.ToInt32, the moment it starts waiting for Connection.InsertAsync it releases control back to its caller.

In other words, the caller will not be stuck waiting for Connection.InsertAsync to finish. The caller will be told "this will take a while, feel free to do something else", so it can continue.

Now, if the caller themselves was explicitly told to await the InsertAsync(TEntity) method on the same line that you call the method, then it will wait and it won't do anything else (except release control back to its caller), but that's because it was explicitly instructed to wait at that point.

To explain in code:

// I will wait for this result
var myInt = await Connection.InsertAsync(myEntity);

// I will not do this until I receive myInt
var sum = 1 + 1;
var anotherSum = 2 + 2;
var andAnotherSum = 3 + 3;

Without the await, the caller will just move on to the next command and do its work, all the way up to the point where it is finally told that it must await the task returned from InsertAsync(TEntity).

To explain in code:

// I will ask for this result but not wait for it
var myIntTask = Connection.InsertAsync(myEntity);

// I will keep myself busy doing this work
var sum = 1 + 1;
var anotherSum = 2 + 2;
var andAnotherSum = 3 + 3;

// My work is done. I hope the task is already done too.
// If not, I will have to wait for it because I can't put it off any longer.
var myInt = await myIntTask;

I've read some threads regards the difference between await and ContinueWith.

Functionally speaking, there is no difference between the two. However, the ContinueWith syntax has recently fallen out of popular favor, and the await syntax is much more favored because it reduces nesting and improves readability.

In terms of waiting, the behavior is exactly the same.

Personally, I suspect that ContinueWith is a leftover artifact from initially trying to design async methods the same way that promises in JS work, but this is just a suspicion.

Upvotes: 3

Theodor Zoulias
Theodor Zoulias

Reputation: 43545

You should definitely prefer async/await over the ContinueWith method.

public async Task<int> InsertAsync(TEntity entity)
{
    var result = await Connection.InsertAsync(entity, Transaction);
    return Convert.ToInt32(result);
}

The primitive ContinueWith method has many hidden gotchas. Exceptions thrown synchronously, exceptions wrapped in AggregateExceptions, TaskScheduler.Current ambiguity, SynchronizationContext not captured, nested Task<Task>s not properly unwrapped, will all come and bite you at one point or another, if you get in the habit of following the ContinueWith route.

Upvotes: 2

JonasH
JonasH

Reputation: 36371

That should be fine. However, there is a recommendation to always pass a taskscheduler to Continue with, to avoid any ambiguity of what context the continuation will run in, even if it does not matter in this particular case.

I would prefer the version

public async Task<int> InsertAsync(TEntity entity)
{
    var r = await Connection.InsertAsync(entity, Transaction);
    return Convert.ToInt32(r);
}

I consider this easier to read, and it will always execute the continuation on the same context as the caller. Behind the scenes it will produce very similar code to your example.

Upvotes: 2

Related Questions