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

时间:2012-11-12 10:04:14

标签: c# entity-framework asynchronous 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();
    }
}

新的调用,在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();
    }
}

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

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

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

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

1 个答案:

答案 0 :(得分: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();
    }
}

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

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

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

(至少这是其他async IO如何在.NET中运行,我假设ADO.NET异步相同)

在另一种情况下:

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

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

对于消费者而言,两种情况的行为都相同,不同之处在于您在上一个示例中占用资源。