如何取消订阅其中的订阅者

时间:2016-12-03 11:41:22

标签: c# events observer-pattern subscribe unsubscribe

我有要做的事件列表。所以我将订阅者添加到订阅列表中。订户完成工作后,必须取消订阅。用户完成时尚不清楚。只有用户自己知道。

最佳设计模式或解决方案是什么。

我使用了观察者模式

这是我的Observable:

internal class EventProvider : IObservable<double>
{
    private readonly List<IObserver<double>> _observers = new List<IObserver<double>>();

    public IDisposable Subscribe(IObserver<double> observer)
    {
        // check if observer exist...
        _observers.Add(observer);
        return new Unsubscriber<double>(_observers, observer);
    }

    public void OnTimingsRecieved(double timing) // some other event fires this
    {
        foreach (var observer in _observers)
        {
            observer.OnNext(timing);
        }
    }        

    //...
}

这是观察者:(可以有0到多个观察者)

internal class EventObserver : IObserver<double>
{
    private IDisposable _unsubscriber;
    private readonly IReadOnlyList<Event> _events;

    public EventObserver(IReadOnlyList<Event> events)
    {
        _events = events;
    }

    public void Subscribe(EventProvider provider)
    {
        _unsubscriber = provider.Subscribe(this);
    }

    private int _ind;
    public void OnNext(double timings)
    {
        // may move to next event or not. it depends.
        // _ind++; may execute or not 

        if (_ind == _events.Count) OnCompleted(); // time to unsubscribe it self
    }

    public void OnCompleted()
    {
        _unsubscriber.Dispose();
    } 

    //...
}

这是像往常一样实施的Unsubscirber。

internal class Unsubscriber<T> : IDisposable
{
    private readonly List<IObserver<T>> _observers;
    private readonly IObserver<T> _observer;

    internal Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer)
    {
        _observers = observers;
        _observer = observer;
    }

    public void Dispose()
    {
        if (_observers.Contains(_observer))
            _observers.Remove(_observer);
    }
}

当我尝试在OnNext事件中部署观察者时出现问题。因为我在foreach循环中而修改了集合,我处理了,即从列表中删除了元素。

您如何处理自己想要取消订阅订阅者的情况?有没有更好的设计模式?

我很欣赏看到不同的方法,而不是使用可观察和观察者。

假设你有这个事件。

public event EventHandler<double> TimeDiff;

您有许多订阅者附加到TimerDiff并且能够取消订阅。

public class Reciever
{
    Jobs listOfJobsToDo;

    public void TimeDiffRecieved(double diff)
    { 
       listOfJobsToDo.DoJob(diff);
       if(somecondition)
           Unsubscribe();
    }
}

1 个答案:

答案 0 :(得分:0)

由于foreach无法处理我用于循环的集合更改。

在这种情况下,我们知道当观察者工作时,它可以自行处理。和其他人不受影响。

以下是对提供者的更正。

public void OnTimingsRecieved(double timing)
{
    for (int i = 0; i < _observers.Count; i++)
    {
        var count = _observers.Count;  // save count in case it may change.
        var observer = _observers[i];
        observer.OnNext(timing);        // it may only dispose it self.
        i -= count - _observers.Count; // decrement if observer unsubscribed.
    }
}