'使用'语句与'最后尝试'
我有一堆属性,我将使用读/写锁。 我可以用一个实现它们try finally
或using
条款。
在try finally
的try finally
我会在try
之前获得锁定,并在finally
释放。 在using
子句中,我将创建一个在其构造函数中获取锁的类,并在Dispose方法中释放它。
我在很多地方都使用读/写锁,所以我一直在寻找比try finally
更简洁的方法。 我有兴趣听到一些关于为什么不推荐一种方式或为什么可能比另一种更好的想法。
方法1( try finally
):
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
rwlMyLock_m .AcquireReaderLock(0);
try
{
return dtMyDateTime_m
}
finally
{
rwlMyLock_m .ReleaseReaderLock();
}
}
set
{
rwlMyLock_m .AcquireWriterLock(0);
try
{
dtMyDateTime_m = value;
}
finally
{
rwlMyLock_m .ReleaseWriterLock();
}
}
}
方法2:
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
using (new ReadLock(rwlMyLock_m))
{
return dtMyDateTime_m;
}
}
set
{
using (new WriteLock(rwlMyLock_m))
{
dtMyDateTime_m = value;
}
}
}
public class ReadLock : IDisposable
{
private ReaderWriterLock rwl;
public ReadLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireReaderLock(0);
}
public void Dispose()
{
rwl.ReleaseReaderLock();
}
}
public class WriteLock : IDisposable
{
private ReaderWriterLock rwl;
public WriteLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireWriterLock(0);
}
public void Dispose()
{
rwl.ReleaseWriterLock();
}
}
从MSDN开始,使用Statement(C#Reference)
使用语句确保即使在对象上调用方法时发生异常,也会调用Dispose。 将对象放在try块中,然后在finally块中调用Dispose,可以获得相同的结果; 实际上,这是编译器如何翻译using语句。 前面的代码示例在编译时展开为以下代码(请注意额外的大括号来为对象创建有限的作用域):
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
所以基本上, 它是相同的代码,但有一个很好的自动空值检查和一个额外的变量范围 。 该文档还指出,它“确保正确使用IDisposable对象”,因此您可能会在将来为任何不明确的情况提供更好的框架支持。
所以选择2。
将变量放在不再需要的范围内后立即结束。
我绝对更喜欢第二种方法。 它在使用点更简洁,并且更少出错。
在第一种情况下,编辑代码的人必须小心,不要在Acquire(Read | Write)Lock调用和try之间插入任何内容。
(对这样的单个属性使用读/写锁通常是过度的,它们最好应用在更高层次上,一个简单的锁往往足够用于这里,因为考虑到锁持有的时间,争用的可能性可能非常小并且获取读/写锁是比简单的锁更昂贵的操作)。
考虑两种解决方案都不好,因为它们会掩盖异常 。
一个没有catch
的try
显然应该是一个坏主意; 请参阅MSDN,了解为什么using
语句同样是危险的。
另请注意,Microsoft现在推荐使用ReaderWriterLockSlim而不是ReaderWriterLock。
最后,请注意Microsoft示例使用两个try-catch块来避免这些问题,例如
try
{
try
{
//Reader-writer lock stuff
}
finally
{
//Release lock
}
}
catch(Exception ex)
{
//Do something with exception
}
一个简单的,一致的,干净的解决方案是一个很好的目标,但假设你不能只使用lock(this){return mydateetc;}
,你可能会重新考虑这个方法; 与更多的信息,我敢肯定堆栈溢出可以帮助;-)