异步EF 6与包裹同步EF

时间:2015-05-19 17:23:29

标签: c# entity-framework asynchronous

所以..这可能是一个愚蠢的问题。我无法完全理解为什么使用EF6 Async会提高性能,而不是在任务中包装同步EF6调用(假设db调用在Web API REST api方法中)

即,这是为什么:

//wrapping synch with asynch
return await Task.Run(() =>
{
    var albums = this.context.Albums
                .Where(x => x.Artist.ID == artist.ID)
                .ToList();
    return albums;
});

比这更糟糕:

//using async 
return await this.context.Albums
            .Where(x => x.Artist.ID == artist.ID)
            .ToListAsync();

注意:我已经阅读了这篇文章http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx,它似乎说(过度简化)“不只是包装同步方法,更有效地重写方法”。

问题1 ,这是EF6异步实现的功能吗?我假设它在实现中使用异步I / O?

问题2 (以及我真正的问题) - 有人可以解释为什么这样更好?在db操作完成之前,两个实现是否都不会导致请求线程自由处理其他请求?

1 个答案:

答案 0 :(得分:5)

让我们说你正在享受一顿丰盛的节日晚宴。这将是大量的食物,包括一个大鸡的主菜。这需要很长时间才能煮熟,所以你要做好准备并将其早早放入烤箱,设定一个计时器以便稍后再检查,然后继续准备下一道菜(土豆泥)。

你不能只是坐在那里等待(同步)那只鸡完成;当你去准备所有其他菜肴时,你需要让它(异步)烹饪。如果你在开始工作之前等待鸡肉完成其他任何事情,除了你非常无聊之外,当你完成其他所有事情时,鸡肉会被冰冷。

现在有几种方法可以让你在做其他工作时进行这项操作(让鸡肉做饭)。例如,您可以设置计时器,并在计时器通知您时间已到时立即检查计时器。另一种解决方案是不能自己动手。你可以去抓住你的儿子并告诉他只是坐在炉子前等待鸡准备好,让他在准备好时通知你。

使用计时器类似于单线程异步解决方案。 (每个人都是一个线程。)只有一个工人(你),你开始异步工作,有异步通知,你需要什么时候做,但一次只做一件事。在厨房中有多个人类似于多线程应用程序。如果您正在使用这些多人实际执行多项任务,这些任务需要一个真正的人同时工作(例如,当您的儿子正在洗芦笋时,您正在捣碎土豆),那么您&#39 ;让你的工作更快完成。当你使用那个额外的人(线程)做什么,除了坐在那里等待一些事情完成,当你去做工作,那么你只是在浪费那个人(线程和' s) #39; s)时间;他们宁愿去做一些富有成效的事情。

因此,要完全剥离类比,当您使用Task.Run同步执行IO时,您需要在线程池中调度工作,其中分配的线程只需坐在那里无所事事(而不是实际执行)等待IO完成时的生产性工作)。当您只使用固有的异步IO操作时,根本不涉及其他任何线程