【问题标题】:IQueryable async extension methods exact time execution and returned taskIQueryable 异步扩展方法精确时间执行和返回任务
【发布时间】:2018-03-29 22:21:39
【问题描述】:

我有一个从数据库返回数据的方法

public Task<List<T>> GetAsync(int someId)
    {
        return dbSet
            .Where(x => x.Id == someId)
            .ToListAsync();
    }

我有一个字典,通过某个键存储任务

Dictionary<int, Task<List<T>>> SomeDictionary { get; set; }

在其他地方,我得到了任务并将其放入字典中

var someTask = repo.GetAsync(someId);
someInstance.AddInDictionary(key, someTask);

然后我得到任务,等待它得到结果

var task = someInstance.GetFromDictionary(key);
List<T> result = await task;

所以我的问题是: 1、IQueryable在哪里翻译成sql查询并在数据库中执行: 当我在 repo 中调用方法时

var someTask = repo.GetAsync(someId); 

-或者当我等待任务时

List<T> result = await task;

2。在字典中,当我存储任务时

Dictionary<int, Task<List<T>>> SomeDictionary { get; set; }

...我是只存储一个应该返回结果的操作,还是将一个操作与实际结果一起存储?换句话说,保存任务而不是保存列表会节省内存吗?

提前致谢。

【问题讨论】:

  • 我的猜测是ToListAsync(),和ToList()一样
  • 你想知道什么时候执行的目的是什么?

标签: c# entity-framework asynchronous task iqueryable


【解决方案1】:

await 关键字实际上是语法糖。它以与回调相似(不相同)的方式工作,其中回调是执行await 的代码。它不控制Task 的执行时间或方式。

这意味着实体框架负责在不知道await 的情况下调度和执行Task,因此可以根据需要调度Task 的执行。

根据ToListAsync 的实现方式,它可能包含一部分与当前线程立即同步执行的代码。

我没有看到 Microsoft 状态何时IQueryable 被转换为 SQL,或者与 SQL 服务器的连接已启动。我的猜测是IQueryable 被转换为 SQL,并且连接握手在调用ToListAsync 时立即开始,并且该方法的其余部分会尽快在ThreadPool 线程之一上执行。

话虽如此,调用代码的编写方式应该不依赖于异步方法的内部操作。

至于你问题的第二部分,Task 是一个引用类型。它与任何其他引用类型具有相同的memory overhead。如果将N 字段声明为容纳N Tasks,您将得到N * B bits,其中B 是3264,具体取决于您的操作系统。如果将它们存储在 List(也是一个引用类型)中,您最终可能会消耗更多内存,因为 List 在内部保留了一个比所需更大的数组,因此它可以更有效地附加/前置项目。如果您将N Tasks 存储在ArrayN 元素中,您最终会得到(N + 1) * B(可能更多,不确定),因为数组也是一个引用。

【讨论】:

  • 感谢您的回答。我想知道,因为它与我的第二个问题有关(也有一定的好奇)。
  • 为您问题的第二部分编辑。 :D
  • 我刚刚看到了编辑...所以 IEnumerable 存储指向对象而不是对象的指针?
  • IEnumerable 是一个接口。它不存储任何东西(尽管 CLR 确实将它的类型定义保存在内存中)。 List&lt;T&gt;Array&lt;T&gt; 都实现了 IEnumerable,但 IEnumerable 与项目的存储无关,而是与如何访问这些项目有关。
  • 你说得对,我的意思是 IEnumerable 实现。
猜你喜欢
  • 1970-01-01
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多