C# 在多个方法调用上使用asyc/wait/task

C# 在多个方法调用上使用asyc/wait/task,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我一直在尝试理解async/await,以确保从数据库加载内容时UI不会阻塞。到目前为止,这就是我所拥有的,但它根本不起作用: 虚拟机: 公共加载视图模型(IRoleService角色服务) { 角色服务=角色服务; 惊人的负荷(); } 私密的、令人吃惊的 { Roles=RoleService.GetAllRoles(); } 角色服务: public IEnumerable<Role> GetAllRoles() { return Repository.GetAll&

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

虚拟机:

公共加载视图模型(IRoleService角色服务)
{
角色服务=角色服务;
惊人的负荷();
}
私密的、令人吃惊的
{
Roles=RoleService.GetAllRoles();
}
角色服务:

public IEnumerable<Role> GetAllRoles()
{
    return Repository.GetAll<Role>().Result;
}
public async Task<IEnumerable<Role>> GetAllRolesAsync()
{
    return await Repository.GetAll<Role>();
}
public IEnumerable GetAllRoles()
{
返回Repository.GetAll().Result;
}
存储库:

public async Task<IQueryable<T>> GetAll<T>() where T : class
{
    return await Task.Run(() => Context.Set<T>());
}
    public async Task<IQueryable<T>> GetAll<T>() where T : class
    {
        return await Task.Run(() => Context.Set<T>());
    }
public async Task GetAll(),其中T:class
{
返回wait Task.Run(()=>Context.Set());
}
我认为这可以工作,但显然不行,因为UI仍然挂起。我确实是通过在角色服务中创建另一个任务来实现的,但我认为你不应该做越来越多的任务

我试了一段时间,读了很多关于它的书,但我就是不明白

有人能解释一下为什么这不起作用,以及我怎样才能真正让它起作用吗

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

虚拟机:

公共加载视图模型(IRoleService角色服务)
{
角色服务=角色服务;
//以后再换
变量角色=惊人的加载();
}
私有异步任务加载()
{
var roles=await RoleService.GetAllRolesAsync();
foreach(角色中的var角色)
{
Console.WriteLine(role.Name);
}
返回角色;
}
角色服务:

public IEnumerable<Role> GetAllRoles()
{
    return Repository.GetAll<Role>().Result;
}
public async Task<IEnumerable<Role>> GetAllRolesAsync()
{
    return await Repository.GetAll<Role>();
}
public异步任务GetAllRolesAsync()
{
return wait Repository.GetAll();
}
存储库:

public async Task<IQueryable<T>> GetAll<T>() where T : class
{
    return await Task.Run(() => Context.Set<T>());
}
    public async Task<IQueryable<T>> GetAll<T>() where T : class
    {
        return await Task.Run(() => Context.Set<T>());
    }
public async Task GetAll(),其中T:class
{
返回wait Task.Run(()=>Context.Set());
}

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

您正在调用任务的
结果,它会同步等待任务完成。由于您是从UI线程调用它,因此它将在该任务执行期间阻止UI线程。由于该任务需要向UI线程发出回调,并且您正在阻止UI线程并阻止处理任何UI消息,因此该任务当然永远不会完成,从而导致UI永远挂起


您不需要同步等待异步操作;您需要整个调用堆栈是异步的。(您需要“一路异步”。

+1。对于“异步构造函数”的特殊情况,我有-也可以参见。请注意,必须同步将ViewModels构造为“加载”状态,然后异步将其更新为“加载”状态。谢谢您的回答。你能再看一下吗?我仍然无法让它工作,即使我现在正在异步整个调用堆栈…@Bv202您需要记住,
IQueryable
是查询的表示,而不是该查询的结果。创建
IQueryable
几乎不需要时间,因为它只创建了一个对象,在迭代时可以用来执行数据库查询。只有在迭代时,才真正查询数据库。您正在异步构造查询,并同步执行它。好的,谢谢您提供的信息,我理解您的意思。但如何解决这个问题呢?为了实际执行查询(通过使用ToList()或其他方法),我必须获取Result属性,但我无法在此处访问它,或者异步代码停止?@Bv202您应该做的是使用EF的方法异步执行查询,即
ToListAsync
,并避免同步等待来自线程池线程的异步IO。