mdziadowiec
mdziadowiec

Reputation: 406

Unsubscribing from event when object is disposed

What I'm trying to figure out is how to declaratively avoid the Object reference not set to an instance of an object exception thrown when disposing of subscription to FromEventPattern observable when the observed object gets disposed of before disposing of the subscription. Here's a simplified example:

void Main()
{
    EventSource oEventSource = new();
    
    var source = Observable.FromEventPattern<MyEventArgs>(
                h => oEventSource.MyEvent += h,
                h => {
                    //if (oEventSource != null) 
                    oEventSource.MyEvent -= h; // <--- error thrown here
                })
        .Select(x => x.EventArgs.Value)
        .Subscribe(x => Console.WriteLine(x));

    Observable.Interval(TimeSpan.FromMilliseconds(500)).Subscribe(x =>
    {
        oEventSource?.RaiseMyEvent(x);
    });
        
    Thread.Sleep(3000);
    oEventSource = null;
    
    Thread.Sleep(2000);
    source.Dispose(); // <--- error thrown when disposing subscription
}


public class EventSource
{
    public event EventHandler<MyEventArgs> MyEvent;
    
    public void RaiseMyEvent(long x){
        MyEvent?.Invoke(this, new MyEventArgs(x));
    }
}

public class MyEventArgs : EventArgs
{
    public MyEventArgs(long x) { Value = x;}
    public long Value { get; set; }
}

I cannot make sure the subscription is disposed of before disposing of the "EventSource" object because the object is defined in viewModel and it is bound to the View where the subscription takes place.

Checking if EventSource object exists before removing the handler stops the error being raised (if (oEventSource != null)), but won't it introduce a memory leak since the handler is never removed?

Upvotes: 0

Views: 417

Answers (1)

Apostolis Bekiaris
Apostolis Bekiaris

Reputation: 2275

there is much confusion to your logic and your style is not really using RX e.g sequence composability. However an answer to your question is simply unsubscribe your source uppon the condition you want

.Select(x => x.EventArgs.Value)
    .TakeUntil(l => oEventSource!=null)  //this line
    .Subscribe(x => Console.WriteLine(x));

Upvotes: 1

Related Questions