I want to synchronize access to a BehaviorSubject<T>
, so I'm looking to use Subject.Synchronize
. However, I have a couple of pain points with this interface and am wondering whether I'm missing a more agreeable way of doing things.
Firstly, I am forced to store both the original subject and the synchronized subject. This is because I sometimes use the Value
property on BehaviorSubject<T>
. It's also because the return value of Synchronize
is not disposable, so I must needs store an instance of the original subject in order to dispose it correctly.
Secondly, the return value of Synchronize
is ISubject<TSource, TResult>
, which is not compatible with ISubject<T>
.
Thus I end up with code like this:
public class SomeClass
{
private readonly BehaviorSubject<string> something;
private readonly ISubject<string, string> synchronizedSomething;
public SomeClass()
{
this.something = new BehaviorSubject<string>(null);
// having to provide the string type here twice is annoying
this.synchronizedSomething = Subject.Synchronize<string, string>(this.something);
}
// must remember to use synchronizedSomething here (I forgot and had to edit my question again, showing how easy it is to screw this up)
public IObservable<string> Something => this.synchronizedSomething.AsObservable();
// could be called from any thread
public void SomeMethod()
{
// do some work
// also must be careful to use synchronizedSomething here
this.synchronizedSomething.OnNext("some calculated value");
}
public void Dispose()
{
// synchronizedSomething is not disposable, so we must dispose the original subject
this.something.Dispose();
}
}
Is there a cleaner/better approach that I'm missing? Just to be clear, what I would love to be able to do instead is something like this (pseudo code):
public class SomeClass
{
private readonly IBehaviorSubject<string> something;
public SomeClass()
{
this.something = new BehaviorSubject<string>(null).Synchronized();
}
public IObservable<string> Something => this.something.AsObservable();
// could be called from any thread
public void SomeMethod()
{
// do some work
this.something.OnNext("some calculated value");
}
public void Dispose()
{
this.something.Dispose();
}
}