C# 如何使用PLINQ实现延迟加载?
linq的一个优点是可以根据请求延迟处理无限的数据源。我尝试并行化我的查询,发现延迟加载不起作用。例如C# 如何使用PLINQ实现延迟加载?,c#,lazy-loading,plinq,C#,Lazy Loading,Plinq,linq的一个优点是可以根据请求延迟处理无限的数据源。我尝试并行化我的查询,发现延迟加载不起作用。例如 class Program { static void Main(string[] args) { var source = Generator(); var next = source.AsParallel().Select(i => ExpensiveCall(i)); foreach (var i in next)
class Program
{
static void Main(string[] args)
{
var source = Generator();
var next = source.AsParallel().Select(i => ExpensiveCall(i));
foreach (var i in next)
{
System.Console.WriteLine(i);
}
}
public static IEnumerable<int> Generator()
{
int i = 0;
while (true)
{
yield return i;
i++;
}
}
public static int ExpensiveCall(int arg)
{
System.Threading.Thread.Sleep(5000);
return arg*arg;
}
}
类程序
{
静态void Main(字符串[]参数)
{
变量源=生成器();
var next=source.AsParallel().Select(i=>ExpensiveCall(i));
foreach(下一个中的变量i)
{
系统控制台写入线(一);
}
}
公共静态IEnumerable生成器()
{
int i=0;
while(true)
{
收益率i;
i++;
}
}
公共静态内部费用调用(内部参数)
{
系统线程线程睡眠(5000);
返回arg*arg;
}
}
这个程序无法产生任何结果,大概是因为在每一步中,它都在等待对生成器的所有调用停止,当然这永远不会发生。如果我打“Asparalle”电话,效果很好。那么,在使用PLINQ提高应用程序性能的同时,如何获得良好的延迟加载呢
我认为你混淆了两件不同的事情。这里的问题不是延迟加载(即只加载所需的量),这里的问题是输出缓冲(即不立即返回结果) 在你的情况下,你最终会得到你的结果,尽管这可能需要一段时间(对我来说,它需要大约500个结果才能返回第一批)。缓冲是出于性能原因而进行的,但在您的情况下,这没有意义。正如Ian正确指出的,您应该使用
.WithMergeOptions(ParallelMergeOptions.NotBuffered)
禁用输出缓冲
但是,据我所知,PLINQ不做延迟加载,也没有办法改变这一点。这意味着,如果您的消费者(在您的情况下,
foreach
循环)太慢,PLINQ将以超出必要的速度生成结果,并且仅当您完成迭代结果时才会停止。这意味着PLINQ可能会浪费CPU时间和内存。非常好的一点。。。PLINQ中的缓冲只掩盖了没有延迟加载的问题。也许一种方法是使用一个扩展方法,对接下来的n个项进行批处理,并并行执行这些项,然后返回结果。这可能会产生虚假的懒惰行为…@tbischel是的,类似的事情会奏效。另一个选项是使用BlockingCollection
和BoundedCapacity
设置。
var next = source.AsParallel()
.WithMergeOptions(ParallelMergeOptions.NotBuffered)
.Select(i => ExpensiveCall(i));