EF中这两个异步调用有什么区别?

Álv*_*cía 5 c# asynchronous entity-framework async-await

我在EF6中看到了一个新功能,即异步方法.我找到了一个例子.

第一种方式是普通呼叫,例如EF5:

public Store FindClosestStore(DbGeography location)
{
    using (var context = new StoreContext())
    {
        return (from s in context.Stores
           orderby s.Location.Distance(location)
           select s).First();
    }
}
Run Code Online (Sandbox Code Playgroud)

和新的调用,在EF6中使用异步方法.

public async Task<Store> FindClosestStore(DbGeography location)
{
    using (var context = new StoreContext())
    {
        return await (from s in context.Stores
            orderby s.Location.Distance(location)
            select s).FirstAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我可以执行以下操作(语法是aprox,我是通过内存执行的):

public async Task<Store> MyAsyncMethod(DbGeography location)
{
     return await Task.Run(() => FindClosestStore());
}
Run Code Online (Sandbox Code Playgroud)

我的意思是,我可以使用Task.Run调用第一个方法,即没有异步,等待结果.目前,是我用来调用异步任何方法的方式,而不仅仅是EF.这也是异步调用,或者当我使用EF6异步方法时真正的异步调用?

为什么在新版本的EF6中需要异步方法?只是为了简单?

Rog*_*son 9

这里的不同之处在于代码如何等待.

在这段代码中:

public async Task<Store> FindClosestStore(DbGeography location)
{
    using (var context = new StoreContext())
    {
        return await (from s in context.Stores
            orderby s.Location.Distance(location)
            select s).FirstAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

EF将对数据库发出查询,然后返回.

结果返回后,任务将完成,await块将继续执行.

也就是说,.NET本身没有等待响应的线程.(希望)有一个来自db驱动程序的低级回调,它会在结果到达时通知.NET.

(这至少是.NET中其他异步IO的工作方式,我假设ADO.NET异步相同)

在另一种情况下:

public async Task<Store> MyAsyncMethod(DbGeography location)
{
     return await Task.Run(()=> FindClosestStore());
}
Run Code Online (Sandbox Code Playgroud)

将有一个线程等待来自DB的响应.也就是说,你将拥有阻止IO,但它会被你的task.run技巧隐藏在消费者手中.

这两种情况对于消费者而言都是相同的,不同之处在于您在最后一个示例中占用了资源.

  • 在最后一个代码示例中,将有一个阻塞线程,因为它使用非异步EF方法.即使你在async/await块中包装该调用.那是."FindClosestStore()"将阻止幕后的线程 (2认同)