• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

c# - EF 数据上下文 - 异步/等待和多线程

[复制链接]
菜鸟教程小白 发表于 2022-8-20 17:47:49 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我经常使用 异步/等待 以确保 ASP.NET MVC Web API 线程不会被长时间运行的 I/O 和网络操作(特别是数据库调用)阻塞。

System.Data.Entity namespace 在这里提供了多种辅助扩展,例如 FirstOrDefaultAsync、ContainsAsync、CountAsync 等。

但是,由于数据上下文不是线程安全的,这意味着以下代码有问题:

var dbContext = new DbContext();
var something = await dbContext.someEntities.FirstOrDefaultAsync(e => e.Id == 1);
var morething = await dbContext.someEntities.FirstOrDefaultAsync(e => e.Id == 2);

事实上,我有时会看到异常(exception)情况,例如:

System.InvalidOperationException: The connection was not closed. The connection's current state is open.



那么使用单独的 using(new DbContext...) 是正确的模式吗?为每个对数据库的异步调用阻塞?那么只执行同步是否可能更有益?



Best Answer-推荐答案


我们在这里陷入了僵局。 AspNetSynchronizationContext ,负责ASP.NET Web API执行环境的线程模型,不保证await之后的异步继续。将在同一线程上进行。这样做的整个想法是使 ASP.NET 应用程序更具可扩展性,从而减少来自 ThreadPool 的线程。被挂起的同步操作阻塞。

然而, DataContext class (part of LINQ to SQL )
不是线程安全的,因此不应在可能跨 DataContext 发生线程切换的地方使用它。 API 调用。单独的 using构造每个异步调用将 不是 帮助,或者:

var something;
using (var dataContext = new DataContext())
{
    something = await dataContext.someEntities.FirstOrDefaultAsync(e => e.Id == 1);
}

那是因为 DataContext.Dispose可能会在与最初创建对象的线程不同的线程上执行,这不是 DataContext会期待。

如果您想坚持使用 DataContext API,调用它 同步似乎是唯一可行的选择。我不确定该语句是否应该扩展到整个 EF API,但我想任何使用 DataContext 创建的子对象API 也可能不是线程安全的。因此,在 ASP.NET 中,他们的 using范围应限制在两个相邻 await 之间的范围内调用。

卸载一堆同步 DataContext 可能很诱人使用 await Task.Run(() => { /* do DataContext stuff here */ }) 调用单独的线程.但是,那将是 a known anti-pattern ,尤其是在 ASP.NET 的上下文中,它可能只会损害性能和可伸缩性,因为它不会减少满足请求所需的线程数。

不幸的是,虽然 ASP.NET 的异步架构很棒,但它仍然与一些已建立的 API 和模式不兼容(例如,这里是 a similar case)。
这尤其令人难过,因为我们在这里不处理并发 API 访问,即只有一个线程试图访问 DataContext同时对象。

希望微软能在框架的 future 版本中解决这个问题。

[更新] 但是,在大规模上,可以将 EF 逻辑卸载到一个单独的进程(作为 WCF 服务运行),该进程将为 ASP.NET 客户端逻辑提供线程安全的异步 API。此类过程可以使用自定义同步上下文作为事件机进行编排,类似于 Node.js。它甚至可以运行一个类似 Node.js 的单元池,每个单元维护 EF 对象的线程关联。这将允许仍然受益于异步 EF API。

[更新] 这是some attempt找到解决此问题的方法。

关于c# - EF 数据上下文 - 异步/等待和多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20946677/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap