长期订阅Rx主题会导致大量内存泄漏

时间:2019-07-04 12:44:50

标签: c# queue system.reactive

我已经实现了一种非常幼稚的内存扇出排队机制,如下所示:

public class ObservableQueue<T> : IObservableQueue<T>
{
    private readonly Subject<T> queue;

    public IObservable<T> Messages => queue.AsObservable();

    public ObservableQueue()
    {
        queue = new Subject<T>();
    }

    public void Enqueue(T item)
    {
        queue.OnNext(item);
    }

    public void Enqueue(List<T> items)
    {
        items.ForEach(queue.OnNext);
    }
}

我之所以选择此实现,是因为它允许极具表现力的订阅,我非常喜欢这种订阅,如下所示:

subscription = queue.Messages
    .Select(data => data.ToJson())
    .Buffer(TimeSpan.FromSeconds(10), ByteSize.FromBytes(128))
    .Where(Enumerable.Any)
    .Select(ToQuery)
    .Subscribe(query => db.Execute(query));

这里使用的Buffer方法再次是我的一个天真的实现:

public static IObservable<IList<string>> Buffer(this IObservable<string> source, TimeSpan timeSpan, ByteSize size) 
{
    // Completes when the `timespan` has elapsed
    var timer = Observable.Timer(timeSpan).Select(_ => new Unit());
    // Completes when the ByteSize exceeds `size`
    var bytes = source
        .Scan(ByteSize.FromBytes(0),
                    (a, b) => a + ByteSize.FromBytes(Encoding.Unicode.GetByteCount(b)))
        .SkipWhile(a => a < size)
        .Select(_ => new Unit()); // We only want to use these for notification, and both observables
                                  // need to be of the same type, so we just emit Unit

    // Amb races the two observables to see which one finishes first, which then propagates the notification
    // and signals the source to strop buffering
    return source.Buffer(() => Observable.Amb(timer, bytes));
}

现在,当我在第二个代码块中创建预订时,内存使用量将急剧增加,罪魁祸首是Subject<T>中的ObservableQueue<T>。我要强调一点,此时尚未Enqueue d实际数据。 subscription已创建,仍在等待任何数据实际处理。

我可以在这里看到一些潜在的罪魁祸首:

  • queue.AsObservable()
  • 我编写的自定义Buffer方法
  • subscription寿命长的事实

但是,我还无法在这里查明实际的根本原因。有什么想法吗?

注意:我认为很明显我不太了解System.Reactive,因此,如果我在这里写了些愚蠢的东西,我会道歉。

0 个答案:

没有答案