Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A second operation cannot be started when using ContinueWith

I have a loop and within the loop I'm doing:

await Task.Delay(1000, ct).ContinueWith(async _ =>
{
    await SecondMethodAsync(ct);
});

The second method gets an entity using EF, sets some properties and saves the entity back to the datastore by calling await SaveChangesAsync() on the DbContext.

The above should wait for 1s and then continue with the second method. With the above implementation I get the following exception:

A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

When I change the above to:

await Task.Delay(1000, ct);
await SecondMethodAsync(ct);

Everything works fine.

What is the difference with the above 2 snippets and how do I get to make the first snippet work?

like image 513
Ivan-Mark Debono Avatar asked Feb 06 '26 22:02

Ivan-Mark Debono


2 Answers

From A Tour of Task, Part 7: Continuations by the async/await guru Stephen Cleary:

In conclusion, I do not recommend using ContinueWith at all, unless you are doing dynamic task parallelism (which is extremely rare). In modern code, you should almost always use await instead of ContinueWith. There are several benefits to await.

You know the solution and it's great:

await Task.Delay(TimeSpan.FromSeconds(1), ct);
await SecondMethodAsync(ct);
like image 194
tymtam Avatar answered Feb 08 '26 22:02

tymtam


I think the reason is the following. Please correct me anybody if I am wrong.

The async lambda inside ContinueWith returns Task, which means the ContinueWith is actually done right after it gets that Task (not when the Task is completed). The program flow goes right into the next loop iteration and hitting that DBContext again.

So the following might also work since the return type of ContinueWith is Task<Task>:

await await Task.Delay(1000, ct).ContinueWith(async _ => {
    await SecondMethodAsync(ct); 
});
like image 40
Michalor Avatar answered Feb 08 '26 22:02

Michalor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!