您的位置:首页 > 其它

对不能用using的成对操作,快速扩展IDisposable的方法

2010-12-09 11:13 232 查看
日常操作中有很多需要打开/关闭 加锁/解锁的成对操作

有时候一些操作原生支持 IDisposable
Monitor 可以用Lock(){} 但是ReadWriteLock 就难了。 还有WCF Channel等)。
这种情况就要用 try/catch/finally,很是丑

封装成IDisposable可能很烦,因为多一个对象要多好多文档。

虽然AOP可能解决一些问题, 但是又没办法精确定位 scrope.
还是 IDisposable +using最爽

所以写了一个缺省实现。

/// <summary>

/// 销毁帮手,生成可以支持using的自定义IDisposable实例
/// <remarks>感谢网友@doggo对于 +=OnDispose功能的測試,由於不完善這裡決定取消該功能</remarks>

/// </summary>

public struct Disposable : IDisposable
{

/// <summary>

/// 创建销毁帮手实例

/// </summary>

/// <param name="onCreate">创建时要做的操作</param>

/// <param name="onDispose">销毁是要做的操作</param>

public Disposable(Action onCreate, Action onDispose)
{
OnDispose = onDispose;

onCreate();

}

/// <summary>

/// 销毁时要做的操作

/// </summary>

private Action OnDispose
{

get ;set;

}

////// <summary>

////// 销毁时要做的操作  支持+=/Addhandler附加操作 (撤銷)

////// </summary>

//////public event Action OnDispose ;

#region IDisposable 成员

void IDisposable.Dispose()
{

OnDispose();

OnDispose = null;

}

#endregion

}


思路是用一个扩展方法,给一个无dispose 能力的对象 建立一个IDisposable的引用。

由于onCreate onDispose是闭包 额外的参数也是非必要的。

这里提供一个简易读写锁的实现。 大家可以参考


实际使用起来就是爽。 这是一个在需要并发访问的队列中 加入对象的方法。

/// <summary>
/// 加入有序队列。
/// </summary>
/// <param name="item">加入的项目</param>
public void Enqueue(TValue item)
{
using (_lock.CreateDisposable(LockType.Write))
{
Queue<TValue> enqueueTarget;
var key=_keySelector(item);
if (!_items.ContainsKey(key))
{
var sortValue = _sortValueSelector(item);
if (!_index.TryGetValue( _sortValueSelector(item) ,out enqueueTarget ))
{
enqueueTarget = new Queue<TValue>();
_index.Add(sortValue, enqueueTarget);
}

enqueueTarget.Enqueue(item);
_items.Add(key, item);
}
else
{
throw new InvalidOperationException("this Item already in queue");
}
}

}


个人工作分享。希望能够帮助大家提高工作效率

附: 容易漏调结束行为的实现 和try catch finally 实现 大家比较下

出异常会死锁的错误成对掉用


正确而麻烦的try catch finally

/// <summary>
/// 加入有序队列。
/// </summary>
/// <param name="item">加入的项目</param>
public void Enqueue2(TValue item)
{
_lock.EnterWriteLock();

try
{
Queue<TValue> enqueueTarget;
var key = _keySelector(item);
if (!_items.ContainsKey(key))
{
var sortValue = _sortValueSelector(item);
if (!_index.TryGetValue(_sortValueSelector(item), out enqueueTarget))
{
enqueueTarget = new Queue<TValue>();
_index.Add(sortValue, enqueueTarget);
}

enqueueTarget.Enqueue(item);
_items.Add(key, item);
}
else
{
throw new InvalidOperationException("this Item already in queue");
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
_lock.ExitWriteLock();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐