Context上的任务和多个操作

时间:2015-02-07 13:29:29

标签: c# entity-framework asynchronous async-await

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

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

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

由于未知原因(可能是一个错误?),我必须使用Task.Run来完成这项工作(存储库只返回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?
    }

}

2 个答案:

答案 0 :(得分:2)

答案是否定的。由于错误表明您不能同时进行2个并发EF操作。以下是对此的更全面的回答:Does Entity Framework support parallel async queries?

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

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?
    }
}

答案 1 :(得分:1)

我认为您处于死锁状态,因为您没有正确使用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线程将恢复。