我有這一小段代碼,模擬使用大對象(那巨大的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異常。 –