C# ASPNet实体框架6-EF6,在同一工作单元中混合异步和同步
我今天遇到了几行代码,归结起来,它们相当于:C# ASPNet实体框架6-EF6,在同一工作单元中混合异步和同步,c#,async-await,entity-framework-6,C#,Async Await,Entity Framework 6,我今天遇到了几行代码,归结起来,它们相当于: using (var db = new AppDbContext()) { var foo = await db.Foos .Where(m => m.Name == "BuzzBaz" ) .FirstAsync(); foo.Name = "Quxx"; db.SaveChanges(); } 请注意,select查询是async,但对SaveChanges()的调用不是。它是同步
using (var db = new AppDbContext())
{
var foo = await db.Foos
.Where(m => m.Name == "BuzzBaz" )
.FirstAsync();
foo.Name = "Quxx";
db.SaveChanges();
}
请注意,select查询是async
,但对SaveChanges()的调用不是。它是同步的
这可能会产生任何问题吗?我应该重构它以使用db.saveChangesSync()吗代码>一切都好吗?或者干脆调用First()
而不是FirstAsync()
?或者它是无害的,可能对整个系统性能有一些好处
我找到一些文档,让我觉得完全删除async
可能是一个不错的选择
在大多数应用程序中,使用异步将没有明显的好处,甚至可能是有害的。在提交之前,请使用测试、评测和常识来衡量特定场景中异步的影响
您的代码实际上是“正确的”,这意味着它没有根本缺陷
让我们分析一下发生了什么,以及我的2美分:
- 在对db进行查询时(即
FirstAsync
),使用wait
意味着指令将按顺序执行,但线程不会被阻塞(异步调用),并且可以用于其他事情。这可能是一件好事,如果这是一个服务器应用程序,您可能希望您的线程能够在等待DB响应时处理其他请求
- 但是,使用非异步
SaveChanges
将阻塞线程。这本身不是一个错误,但由于它也是db上的一个I/O操作,它可能会阻塞线程一段很长的时间。如果您在这里也使用异步版本等待
,它看起来确实更“一致”
这是个问题吗?视情况而定。你的应用程序被大量使用了吗?您的用户在重负载时是否遇到一些低反应性?在这种情况下,在保存时使用异步可能是一种潜在的改进
否则,正如链接的MSDN文章所建议的,在你知道它有影响之前,我的建议是不要太担心
混合使用本身不是问题
就我个人而言,我也会选择异步SaveChanges,以保持一致性,并设想DB写入是一些可能很慢的I/O操作
如果是桌面应用程序,只需确保不阻塞UI线程。
< P>除了编码一致性外,这是非常重要的-考虑以下内容:ConfigureAwait(false)
我通常使所有内容都异步,如果需要同步实现,我更喜欢使用同步版本复制代码。使用
wait
意味着语句将异步执行,执行流将返回给调用方。线程是否被阻塞取决于调用方。@PauloMorgado我不确定使用什么词,但为了让其他读者清楚:async Task MainFunction(){Console.WriteLine(“before”);wait Foo();Console.WriteLine(“after”)}
和async Task Foo(){//在几秒钟内进行长时间的处理…然后:Console.WriteLine(“processed!”):}
将可靠地生成输出:“before”、“processed!”、“after”。在我看来,执行流非常“同步”,这就是等待的
所做的(使异步调用看起来与执行流同步).你不是把顺序和同步混淆了吗?@PauloMorgado很可能!谢谢你的话,我会编辑我的答案的