在多个方法调用中使用 asyc/await/task

Using asyc/await/task over multiple method calls

我一直在努力理解 async/await 以确保 UI 在从数据库加载内容时不会阻塞。这是我目前所拥有的,但它根本不起作用:

虚拟机:

public LoadingViewModel(IRoleService roleService)
{
    RoleService = roleService;
    StartLoading();
}

private IEnumerable<Role> StartLoading()
{
    Roles = RoleService.GetAllRoles();
}

角色服务:

public IEnumerable<Role> GetAllRoles()
{
    return Repository.GetAll<Role>().Result;
}

存储库:

public async Task<IQueryable<T>> GetAll<T>() where T : class
{
    return await Task.Run(() => Context.Set<T>());
}

我认为这可行,但显然行不通,因为 UI 仍然挂起。我确实通过在 RoleService 中创建另一个任务来让它工作,但我认为你不应该做越来越多的任务...

我已经尝试了一段时间,也阅读了很多相关内容,但就是不明白。

有人可以解释为什么这行不通以及我如何才能让它真正起作用吗?

编辑: 看完答案后,我现在有了这个,但它仍然不起作用。稍后再看构造函数问题

虚拟机:

public LoadingViewModel(IRoleService roleService)
{
    RoleService = roleService;

    //change this later
    var roles = StartLoading();
}

private async Task<IEnumerable<Role>> StartLoading()
{
    var roles = await RoleService.GetAllRolesAsync();

    foreach (var role in roles)
    {
        Console.WriteLine(role.Name);
    }
    return roles;
}

角色服务:

public async Task<IEnumerable<Role>> GetAllRolesAsync()
{
    return await Repository.GetAll<Role>();
}

存储库:

    public async Task<IQueryable<T>> GetAll<T>() where T : class
    {
        return await Task.Run(() => Context.Set<T>());
    }

UI 仍然挂起 - 我现在做错了什么?

您正在对任务调用 Result,它会同步等待任务完成。由于您是从 UI 线程调用它,它会在 Task 执行期间阻塞 UI 线程。由于该任务需要 post 回调到 UI 线程,并且您正在阻塞 UI 线程并阻止处理任何 UI 消息,因此 Task 当然永远不会完成,导致 UI 永远挂起。

您需要不同步等待异步操作;您需要整个调用堆栈是异步的。 (你需要"async all the way up"。)