5

我在 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();
    }
}

但是,我可以执行以下操作(语法是近似的,我是靠记忆来做的):

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

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

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

4

1 回答 1

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 将对数据库发出查询,然后返回。

一旦结果返回,任务将完成,等待块将继续执行。

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

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

在另一种情况下:

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

将有一个线程等待数据库的响应。也就是说,您将有阻塞 IO,但它将通过您的 task.run 技巧对消费者隐藏。

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

于 2012-11-12T10:39:42.973 回答