我有这一小段代码,模拟使用大对象(那巨大的byte[]
)的流量。对于序列中的每个项目,调用一个异步方法来获得一些结果。问题?事实上,它会抛出OutOfMemoryException
。无效扩展SelectMany与大对象
代码LINQPad(C#程序)兼容:
void Main()
{
var selectMany = Enumerable.Range(1, 100)
.Select(i => new LargeObject(i))
.ToObservable()
.SelectMany(o => Observable.FromAsync(() => DoSomethingAsync(o)));
selectMany
.Subscribe(r => Console.WriteLine(r));
}
private static async Task<int> DoSomethingAsync(LargeObject lo)
{
await Task.Delay(10000);
return lo.Id;
}
internal class LargeObject
{
public int Id { get; }
public LargeObject(int id)
{
this.Id = id;
}
public byte[] Data { get; } = new byte[10000000];
}
似乎它创建的同时所有对象。我该如何正确地做到这一点?
其基本思想是调用DoSomethingAsync以获得每个对象的一些结果,所以这就是为什么我使用SelectMany。为了简化,我只介绍了一个Task.Delay,但在现实生活中它是一个可以同时处理一些项目的服务,所以我想引入一些并发机制来获得它的优势。
请注意,从理论上讲,处理少量项目的时间不应该填满内存。实际上,我们只需要每个“大对象”来获取DoSomethingAsync方法的结果。在那之后,大对象不再被使用。
我不知道你的问题是否与你的测试代码(Enumerable.Range'急切地创建所有大对象),或者你在生产中看到这个问题?无论哪种方式,如果某个序列创建了许多LargeObjects,并且它们仍在使用,那么不能被GC'ed,那么您会得到一个OOM异常。 –