【发布时间】:2019-01-09 10:21:35
【问题描述】:
我正在读一本书“Terrell R. - Concurrency in .NET”。
有一个很好的代码示例:
Lazy<Task<Person>> person = new Lazy<Task<Person>>(
async () =>
{
using (var cmd = new SqlCommand(cmdText, conn))
using (var reader = await cmd.ExecuteReaderAsync())
{
// some code...
}
});
async Task<Person> FetchPerson()
{
return await person.Value;
}
作者说:
因为 lambda 表达式是异步的,所以可以在 调用 Value 的任何线程,表达式将在 上下文。
据我了解,线程来到 FetchPerson 并卡在 Lamda 执行中。这真的很糟糕吗?有什么后果?
作为解决方案,作者建议创建一个任务:
Lazy<Task<Person>> person = new Lazy<Task<Person>>(
() => Task.Run(
async () =>
{
using (var cmd = new SqlCommand(cmdText, conn))
using (var reader = await cmd.ExecuteReaderAsync())
{
// some code...
}
}));
这真的正确吗?这是一个 IO 操作,但是我们从 Threadpool 中窃取 CPU 线程。
【问题讨论】:
-
不知道为什么作者建议使用
Task.Run,但是在使用 async/await 时我们从不窃取 CPU 线程。当我们调用Task.Run时,确定它可以在线程池上运行,但只有在第一次异步之前的方法的第一部分。一旦它达到异步,它就会返回到线程池。此外,一旦等待完成,它就会返回到原始线程上下文,所以从FetchPerson的角度来看,代码在哪个线程上执行并不重要。
标签: c# asynchronous task lazy-evaluation