我是关于反应的新手,但这个想法让我好奇,所以我做了一个有点反应变量,但我不知道这是不是最好的做法,然后我会把这个线程安全。
这是班级:
public class RxVar<T>:IObservable<T>
{
T _value;
public T Value
{
get{
return _value;
}
set{
if (!_value.Equals(value))
{
onChange(_value);
_value = value;
}
}
}
event onValChange onChange = delegate { };
delegate void onValChange(T val);
IObservable<T> _observable;
public RxVar() {
_observable = Observable.FromEvent<onValChange,T>(ev => onChange += ev, ev => onChange -= ev);
}
public IDisposable Subscribe(IObserver<T> observer)
{
return _observable.Subscribe(p=>observer.OnNext(p));
}
}
信号量示例
_semaphoreSlim.WaitOne();
if (!_value.Equals(value))
{
onChange(_value);
_value = value;
}
_semaphoreSlim.release();
好的,我想让这个帖子安全,我害怕死锁。所以,
使用lock
或信号量更好,或者由于反应性而不需要它?
感谢。 :)
答案 0 :(得分:3)
我建议使用锁而不是信号量。对于这种情况,信号量只是错误的工具。
考虑用“return _value”公开实际值意味着即使在getter返回之后,客户端代码也能够修改对象中的数据。所以问题是你在暴露参考后如何避免竞争条件?
答案是不要暴露参考。给出对象/数据的DEEP COPY,而不是原始对象本身。
关于僵局:如果你知道自己在做什么,就不应该害怕。如果你不这样做,你就无法判断永远不会有死锁,因为在每次运行时条件可能会有所不同,即使经过多次成功的测试,你可能会导致死锁并进行调试,这将是一项艰巨的任务
死锁只能通过事先学习来避免,而不是通过任何“不知道编程”的方式来解决。
带锁的小片段:
类实例字段(如果_value可以为null,则需要此项,否则可以锁定_value本身):
private object _valueLock = new Int(0);
在你的方法中:
lock(_valueLock)
{
if (_value != value) // this or deep equality
{
_value = value;
onChange(this, _value); // for complex Observer-Observable scenarios it's better specifying the observed object
}
}