1

maybe I am wrong and this is actually ok behaviour, but then I dont get, why they would even put the async postfix to the method name and make it awaitable.

Just to easily reproduce, this is enough:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    using var ctx = new eWMSContext();
    var a = await ctx.TJobLines.ToListAsync();
}

This call blocks UI even though it seems it shouldn't and wrapping it to Task.Run doesn't seem logical.

I was unable to find any resource why is it happening.

This resource explains, that it should not block UI, but it does: https://learn.microsoft.com/lt-lt/ef/core/miscellaneous/async

I'm using (all are latest for .NET Core 3.1):
EF Core 3.1.12
Oracle.EntityFrameworkCore 3.19.80
Oracle.ManagedDataAccess.Core 2.19.101

atiyar
  • 7,762
  • 6
  • 34
  • 75
Tomáš Filip
  • 727
  • 3
  • 6
  • 23
  • `ToListAsync()`is the only `async` part of this and the most time (and the blocking) happens on you sync constructor and property getter. – Poul Bak Feb 23 '21 at 22:57
  • Somewhat related: [Why File.ReadAllLinesAsync() blocks the UI thread?](https://stackoverflow.com/questions/63217657/why-file-readalllinesasync-blocks-the-ui-thread). Unfortunately the reality doesn't always match our expectations. Fortunately we have the `Task.Run` to help us in times of need. – Theodor Zoulias Feb 24 '21 at 05:21
  • @PoulBak Hello, it really doesnt. I did the testing and the blocking part is ToListAsync itself. Also the same accoutns for FindAsync, FirstOrDefaultAsync etc... All of EF Core async methods are blocking the UI. – Tomáš Filip Feb 24 '21 at 07:51
  • 2
    Another relevant question: [Can the Oracle Managed Driver use async/wait properly?](https://stackoverflow.com/questions/29016698/can-the-oracle-managed-driver-use-async-wait-properly) – Theodor Zoulias Feb 24 '21 at 08:12
  • 1
    @TheodorZoulias Hey thanks for this link, thats propably it... It is kinda sad to be honest. Anyway thanks for this article – Tomáš Filip Feb 24 '21 at 10:49

1 Answers1

1

Unfortunately, the actual implementation of these methods seem to leave something to be desired:

Why would an EF query with ToListAsync hang in a WPF application?

As a workaround, to keep your UI responsive, you could execute the synchronous version on a background thread:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await Task.Run(() =>
    {
        using var ctx = new eWMSContext()
        {
            var a = ctx.TJobLines.ToList();
        }
    });
}

Then you don't have to rely on the implementation of ToListAsync being non-blocking.

Steve Py
  • 26,149
  • 3
  • 25
  • 43
mm8
  • 163,881
  • 10
  • 57
  • 88
  • 1
    +1. I would suggest to make the `a` variable the result of the `Task.Run` method, because most probably the OP wants to use it to update UI controls. And accessing UI controls from inside the `Task.Run` is an easy and common mistake to make. – Theodor Zoulias Feb 24 '21 at 05:15
  • 1
    Well, this is sad. Why would they implement async fuctions then? Even like FindAsync, FirstOrDefaultAsync block as well.. Thats just sad for me. I dont even see a reason to use the async await. – Tomáš Filip Feb 24 '21 at 07:47
  • @TheodorZoulias I am using MVVM with reactiveUI, this button click is really just for easiest reproduction of the problem. – Tomáš Filip Feb 24 '21 at 07:48
  • 2
    "_Why would they implement async functions then?_" -> because `ToListAsync` can be called against **any** `IQueryable` irrespective as to how it is implemented. You are experiencing a limitation in the Oracle driver. Calling `ToListAsync` using the SQL Server driver (for example) does not block. – Johnathan Barclay Feb 24 '21 at 09:44