wpf - Entity Framework 异步调用阻塞 UI 线程

标签 wpf mvvm async-await entity-framework-6 mvvm-light

我一直在慢慢尝试将我的代码从使用操作委托(delegate)转换为我的 WPF 应用程序中的新任务。我喜欢一个 await 操作可以在同一个方法中运行的事实,大大减少了我需要的方法数量,增强了可读性,并减少了维护。话虽如此,我在调用 EF6 异步方法时遇到了我的代码问题。它们似乎都在同步运行并阻塞了我的 UI 线程。我在我的代码中使用以下技术/框架:

  • .NET 框架 4.5
  • WPF
  • MVVM 轻 5.2
  • 通用工作单元/存储库框架 v3.3.5
    https://genericunitofworkandrepositories.codeplex.com/
  • Entity Framework 6.1.1
  • SQL Server 2008 R2 Express

  • 例如,我有一个 LogInViewModel,它带有一个在我的 WPF 应用程序上单击按钮后执行的命令。这是在构造函数中初始化的命令:
    LogInCommand = new RelayCommand(() => ExecuteLogInCommand());
    

    这是命令体:
    private async void ExecuteLogInCommand()
    {
         // Some code to validate user input
    
         var user = await _userService.LogIn(username, password);
    
         // Some code to confirm log in
    }
    

    用户服务使用使用 MVVM Light 的 SimpleIoC 容器创建的通用存储库对象。 LogIn 方法如下所示:
    public async Task<User> LogIn(string username, string password)
    {
        User user = await _repository.FindUser(username);
    
        if (user != null && user.IsActive)
        {
            // Some code to verify passwords
            return user;
        }
    
        return null;
    }
    

    以及我要登录的存储库代码:
    public static async Task<User> FindUser(this IRepositoryAsync<User> repository, string username)
    {
        return await repository.Queryable().Where(u => u.Username == username).SingleOrDefaultAsync();
    }
    

    SingleOrDefaultAsync() 调用是 Entity Framework 的异步调用。这段代码阻塞了我的 UI 线程。我已经阅读了 Stephen Cleary 和其他人关于异步等待和正确使用的多篇文章。我一直尝试使用 ConfigureAwait(false),但没有成功。我已经让我的 RelayCommand 调用使​​用了 async await 关键字,但没有成功。我已经分析了代码,返回时间最长的行是 SingleOrDefaultAsync() 行。其他一切几乎都是瞬间发生的。在我的代码中对数据库进行其他异步调用时,我遇到了同样的问题。唯一可以立即修复它的是以下内容:
    User user = await Task.Run(() =>
    {
        return _userService.LogIn(Username, p.Password);
    });
    

    但我知道这不是必需的,因为我对数据库的调用是 IO 绑定(bind)的,而不是 CPU 绑定(bind)的。那么,我的应用程序出了什么问题,为什么它会阻塞我的 UI 线程?

    最佳答案

    您的 RelayCommand不是异步的。

    LogInCommand = new RelayCommand(() => ExecuteLogInCommand());
    

    因为没有async/await您的 ExecuteLogInCommand将被同步调用。

    你必须把它改成
    LogInCommand = new RelayCommand(async () => await ExecuteLogInCommand());
    

    使RelayCommand也称为异步。

    关于wpf - Entity Framework 异步调用阻塞 UI 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36245342/

    相关文章:

    c# - 从 ResourceDictionary 设置 WindowStartupLocation 会引发 XamlParseException

    c# - 使用 PRISM 与 WPF 应用程序中的区域对话

    wpf MVVM ObservableCollection<string> 不更新 View

    c# - EF + AutoFac + async "The connection' s 当前状态正在连接”

    C# 异步任务无限期等待

    c# - 可以使值转换器只能由我的用户控件访问吗? (WPF)

    wpf - XamlReader .net 3.5 'trigger type in Style not recognized'

    wpf - 在WPF 4.5中是否已确定放弃空域支持?

    android - 我应该如何在 Android 上使用 MVVM + 数据绑定(bind)创建表单的字段验证

    javascript - 等待通过 call 调用的异步函数或通过 Babel 应用