-1

I'm learning EFCore and IAsyncEnumerable (now with .net 5 and all the expectation) and I'm struggling understanding await foreach because in one test case I made is blocking execution (or that seems to me)

static async Task Main()
{
    await Test().ConfigureAwait(false);

    Debug.WriteLine("this should happen before, isn't it?");
    Console.ReadKey();
}

static async Task Test()
{
    using var ctx = new MyContext();

    var testDbset = ctx.Entries;

    await foreach (var entry in testDbset.ConfigureAwait(false))
    {
        Console.WriteLine(entry.ToString());
    }
}

The problem is the "before" sentence is written the last, not even in the middle; and the console is fully filled in block out of nowhere. The context is querying a localsql db. Is there something I'm not understanding?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
DrkDeveloper
  • 939
  • 7
  • 17
  • 2
    This behavior is not related to `await foreach`. Any `Test` asynchronous method that logged something, would result to the same behavior. You may want to enhance your [async/await](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/) understanding in general. – Theodor Zoulias Nov 23 '20 at 22:24
  • I think I'm starting to understand these things. Main doesn't need to be async, and you only have to remove the 'await' and '.ConfigureAwait(false)' from the 'await Test().ConfigureAwait(false)'. With that, the task starts and Main recovers control. Am I right? – DrkDeveloper Nov 24 '20 at 01:56
  • 1
    If you remove the `await` then the `Test` task becomes fire-and-forget, and this is rarely what you want. In general we keep a reference to all tasks we create, and we `await` them at some point. There are exceptions of course, for example when the task signals its result by some other mechanism, or if it's doing something unimportant like cleaning up some resource to free-up the allocated memory sooner (instead of leaving it to the garbage collector). – Theodor Zoulias Nov 24 '20 at 02:24
  • 2
    `ConfigureAwait(false)` isn't needed in a console or ASP.NET Core application. There's no synchronization context to return to. The code behaves properly too. The main thread is *not* blocked while `Test()` runs. `await` *awaits* another already running asynchronous operation to complete before proceeding *without* blocking the calling thread – Panagiotis Kanavos Nov 24 '20 at 08:24

1 Answers1

2

If you want the message to appear first, don't await the task till after it has been printed.

static async Task Main()  
{
    var task = Test().ConfigureAwait(false);
    Debug.WriteLine("this should happen before, isn't it?");
    await task;
    Console.ReadKey();
}
John Wu
  • 50,556
  • 8
  • 44
  • 80