Context.SaveChangesAsync()阻塞

时间:2017-01-31 12:38:43

标签: c# wpf entity-framework asynchronous sql-server-ce

我目前正在按照MVVM模式并使用实体框架和SQL Servre CE快速构建WPF应用程序原型。

我正在试验AsyncCommand by Stephen Cleary from the MSDN blog

除了仍然阻止用户界面的Context.SaveChangesAsync()之外,一切都运行良好。

这是同步代码,10000"实体"需要约7秒。 (一种非常简单的数据类型):

public int Insert( IEnumerable<Entity> entities )
{
    using( Context context = new Context( ConnectionString ) )
    {
        context.Entities.AddRange( entities );
        return context.SaveChanges();
    }
}

这是仍在阻止UI的异步版本(我也试过没有using语句的版本,但没有帮助):

public async Task<int> InsertAsync( IEnumerable<Entity> entities )
{
  using( Context context = new Context( ConnectionString ) )
  {
    context.Entities.AddRange( entities );
    return await context.SaveChangesAsync();
  }
}

大部分工作都在SaveChangesAsync()进行,并且包装AddRange无效

await Task.Run( () => context.Entities.AddRange(entities));

使用context.SaveChangesAsync().ConfigureAwait(false)也无济于事。

但是,如果我只是包装同步版本,那么它就不会阻塞:

public async Task<int> InsertAsync( IEnumerable<Entity> entities )
{
   return await Task<int>.Run( () => Insert( entities ) ); 
}

使用AsyncCommand从ViewModel调用此代码(请参阅上面的MSDN文章链接):

CreateRandomEntitiesAsyncCommand = AsyncCommand.Create( 
    token => CreateRandomEntitiesAsync(token));

public IAsyncCommand CreateRandomPatientsAsyncCommand { get; private set;  }

public async Task CreateRandomAsync()
{
   int numberToGenerate = 10000;

   // Get all existing unique ids from the data layer, this does not block
   IEnumerable<string> existingUniqueIDs = await dataLayer.GetUniqueIDsNoTrackingAsync();

   // randomly create 10000 entities, ensuring they are unique, does not block either
   Entity[] entities = await Task.Run( () => 
     CreateEntities(numberToGenerate, existingUniqueIDs));

   // this does block, see above
   await dataLayer.InsertAsync( entities );

   // ...
   // Re-fetch all entities from the db and issue PropertyChanged 
   // for the Entities property to refresh the UI.
   // The code above is still blocking if this is commented out.
}

我做错了什么?

中级更新

这个问题似乎与SQL Server CE及其基础实现有关。可能将异步实体框架代码映射到同步代码,以便在UI线程上执行,从而阻止UI。

另见:Blocking behaviour with Entity Framework Async methods and SQL Server Compact

我正在使用(通过NuGet):

  • Microsoft的EntityFramework.SqlServerCompact v6.1.3
  • Microsoft.SqlServerCompact v4.0.8876.1 [这是ADO.Net提供商吗?]

0 个答案:

没有答案