我有一个从数据库中返回数据的方法
public Task<List<T>> GetAsync(int someId)
{
return dbSet
.Where(x => x.Id == someId)
.ToListAsync();
}
我有一个字典,通过某个键存储任务
Dictionary<int, Task<List<T>>> SomeDictionary { get; set; }
在其他地方,我得到了Task并把它放在字典中
var someTask = repo.GetAsync(someId);
someInstance.AddInDictionary(key, someTask);
然后我得到任务并等待它得到结果
var task = someInstance.GetFromDictionary(key);
List<T> result = await task;
所以我的问题是: 1. IQueryable在哪里转换为sql查询并在数据库中执行: 当我在回购中调用方法时
var someTask = repo.GetAsync(someId);
- 当我等待任务时
List<T> result = await task;
2。在字典中,当我存储任务
时Dictionary<int, Task<List<T>>> SomeDictionary { get; set; }
...我只存储应该返回结果的操作,还是存储与实际结果一起的操作?换句话说,保存任务而不是保存列表,保存任何内存吗?
提前致谢。
答案 0 :(得分:2)
await
关键字实际上是语法糖。它以与回调相似的类似(不同)方式工作,其中回调是继续await
的代码。它无法控制Task
何时或如何执行。
这意味着实体框架负责在不知道Task
的情况下安排和执行await
,因此能够根据需要安排Task
的执行。< / p>
根据ToListAsync
的实现方式,它可能包含一部分代码,可以立即执行并与当前线程同步。
将IQueryable
转换为SQL,或者启动了与SQL Server的连接时,我没有看到Microsoft状态。我的猜测是IQueryable
被转换为SQL并且在调用ToListAsync
时立即开始连接握手,并且在{{1}之一上尽快执行该方法的其余部分}线程。
话虽这么说,调用代码应该以不依赖于异步方法的内部操作的方式编写。
至于问题的第二部分,ThreadPool
是引用类型。它与任何其他引用类型具有相同的memory overhead。如果您声明Task
字段要容纳N
N
,那么您最终会得到Tasks
,其中B为N * B bits
或32
,具体取决于你的操作系统。如果将它们存储在64
中,这也是一种引用类型,您可能最终会占用更多内存,因为List
内部保留的数组比必要的大,因此它可以附加/预置项目更有效率。如果您将List
N
存储在Tasks
Array
个元素中,那么您最终会得到N
(可能会更多,不确定),因为数组也是一个参考。