IQueryable 异步扩展方法精确时间执行和返回任务
IQueryable async extension methods exact time execution and returned task
我有一个方法 returns 来自数据库的数据
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。在字典中,当我存储 Tasks
Dictionary<int, Task<List<T>>> SomeDictionary { get; set; }
...我是只存储应该 return 结果的操作,还是与实际结果一起存储的操作?换句话说,保存Task而不是保存List,是否节省内存?
提前致谢。
await
关键字是有效的语法糖。它以与回调相似(不相同)的方式工作,其中回调是执行 await
的代码。它不控制 Task
何时或如何执行。
这意味着Entity Framework在不知道await
的情况下负责调度和执行Task
,因此有能力调度Task
的执行随心所欲。
根据 ToListAsync
的实现方式,它可能包含一部分与当前线程同步执行的代码。
我没有看到 Microsoft 声明 什么时候 IQueryable
被翻译成 SQL,或者与 SQL 服务器的连接是发起。我的猜测是 IQueryable
被转换为 SQL 并且连接握手在调用 ToListAsync
后立即开始,并且该方法的其余部分尽快在其中一个上执行ThreadPool
个线程。
也就是说,调用代码的编写方式应该不依赖于异步方法的内部操作。
至于你问题的第二部分,Task
是引用类型。它与任何其他引用类型具有相同的 memory overhead。如果您声明 N
字段以容纳 N
Tasks
,您最终会得到 N * B bits
,其中 B 是 32
或 64
,具体取决于你的操作系统。如果将它们存储在 List
中,这也是一个引用类型,您最终可能会消耗更多内存,因为 List
内部保留了一个比需要的更大的数组,因此它可以 append/prepend 项目更有效率。如果您将 N
Tasks
存储在 Array
个 N
元素中,您最终会得到 (N + 1) * B
(可能更多,不确定),因为数组也是一个引用。
我有一个方法 returns 来自数据库的数据
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。在字典中,当我存储 Tasks
Dictionary<int, Task<List<T>>> SomeDictionary { get; set; }
...我是只存储应该 return 结果的操作,还是与实际结果一起存储的操作?换句话说,保存Task而不是保存List,是否节省内存?
提前致谢。
await
关键字是有效的语法糖。它以与回调相似(不相同)的方式工作,其中回调是执行 await
的代码。它不控制 Task
何时或如何执行。
这意味着Entity Framework在不知道await
的情况下负责调度和执行Task
,因此有能力调度Task
的执行随心所欲。
根据 ToListAsync
的实现方式,它可能包含一部分与当前线程同步执行的代码。
我没有看到 Microsoft 声明 什么时候 IQueryable
被翻译成 SQL,或者与 SQL 服务器的连接是发起。我的猜测是 IQueryable
被转换为 SQL 并且连接握手在调用 ToListAsync
后立即开始,并且该方法的其余部分尽快在其中一个上执行ThreadPool
个线程。
也就是说,调用代码的编写方式应该不依赖于异步方法的内部操作。
至于你问题的第二部分,Task
是引用类型。它与任何其他引用类型具有相同的 memory overhead。如果您声明 N
字段以容纳 N
Tasks
,您最终会得到 N * B bits
,其中 B 是 32
或 64
,具体取决于你的操作系统。如果将它们存储在 List
中,这也是一个引用类型,您最终可能会消耗更多内存,因为 List
内部保留了一个比需要的更大的数组,因此它可以 append/prepend 项目更有效率。如果您将 N
Tasks
存储在 Array
个 N
元素中,您最终会得到 (N + 1) * B
(可能更多,不确定),因为数组也是一个引用。