Task 和 Context 上的多个操作

Task and multiple operations on Context

我有这段代码可以从我的数据库中检索数据:

public async Task<IEnumerable<Member>> GetAllMembersAsync()
{
    var members = Repository.GetAll<Member>();

    return await Task.Run(() => members.ToListAsync());
}

出于未知原因(也许是错误?),我必须使用 Task.Run 才能完成这项工作(存储库只是 returns 和 DbSet<Member>。如果我不不这样做,我的 UI 永远挂起。

问题是我不能用这种方式同时进行2个数据库操作。如果我这样做,我会得到这个错误:

A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

如您所见,我已经在使用 await

有什么方法可以解决这个问题,这样我就可以同时执行 2 个数据库操作,这样它们就可以按顺序 运行 了吗?

编辑: 调用它的代码:

private async void LoadMembers()
{
    try
    {
        var members = await MemberService.GetAllMembersAsync();

        Members = new ObservableCollection<Member>(members);
    }
    catch (EntityException)
    {
        // connection lost?
    }

}

我认为您处于死锁状态,因为您没有正确使用 configureawait(true)。 你可以做到

public async Task<IEnumerable<Member>> GetAllMembersAsync()
{
   var members = Repository.GetAll<Member>();

   return await Task.Run(() => members.ToListAsync());
}

private async void LoadMembers()
{
   try
   {
       var members = await MemberService.GetAllMembersAsync().ConfigureAwait(true);

       Members = new ObservableCollection<Member>(members);
   }
   catch (EntityException)
   {
    // connection lost?
   }

}

操作完成后,如果从 GUI 线程执行,GUI 线程将恢复。

答案是否定的。由于错误表明您不能同时进行 2 个并发 EF 操作。这是一个更彻底的答案:Does Entity Framework support parallel async queries?

最重要的是,您不需要使用 Task.Run 来解决似乎是死锁的问题。只需使用 ConfigureAwait 即可确保 async 操作不需要 UI SynchronizationContext 即可完成。 (另外,请确保您没有使用 Task.WaitTask.Result 阻塞 async 代码:

public async Task<IEnumerable<Member>> GetAllMembersAsync()
{
    return await Repository.GetAll<Member>().ToListAsync().ConfigureAwait(false);
}

private async void LoadMembers()
{
    try
    {
        var members = await MemberService.GetAllMembersAsync();
        Members = new ObservableCollection<Member>(members);
    }
    catch (EntityException)
    {
        // connection lost?
    }
}