首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >‘'using’语句vs 'try finally‘

‘'using’语句vs 'try finally‘
EN

Stack Overflow用户
提问于 2008-11-10 19:31:57
回答 15查看 63.2K关注 0票数 85

我有一堆属性,我将在这些属性上使用读/写锁。我可以使用try finallyusing子句来实现它们。

try finally中,我会在try之前获取锁,然后在finally中释放。在using子句中,我将创建一个类,该类在其构造函数中获取锁,并在其Dispose方法中释放。

我在很多地方使用读/写锁,所以我一直在寻找比try finally更简洁的方法。我有兴趣听到一些关于为什么一种方法可能不被推荐,或者为什么一种方法可能比另一种更好的想法。

方法1 (try finally):

代码语言:javascript
复制
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();
        }
    }
}

方法二:

代码语言:javascript
复制
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();
    }
}
EN

回答 15

Stack Overflow用户

回答已采纳

发布于 2008-11-10 19:43:02

来自MSDN,using Statement (C# Reference)

using语句可确保即使在调用对象的方法时发生异常,也会调用Dispose。您可以通过将对象放在try块中,然后在finally块中调用Dispose来实现相同的结果;实际上,这就是编译器转换using语句的方式。前面的代码示例在编译时扩展到以下代码(请注意,额外的花括号为对象创建了有限的作用域):

代码语言:javascript
复制
{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

所以基本上,它是相同的代码,但是有一个很好的自动空检查和一个额外的变量作用域。文档还指出,它“确保了IDisposable对象的正确使用”,因此您可能会在将来遇到任何模糊的情况时获得更好的框架支持。

所以使用选项2吧。

将变量放在不再需要它之后立即结束的作用域中也是一个优点。

票数 97
EN

Stack Overflow用户

发布于 2008-11-10 19:36:23

我当然更喜欢第二种方法。它在用法上更简洁,更不容易出错。

在第一种情况下,编辑代码的人必须小心,不要在获取(读|写)Lock调用和try之间插入任何内容。

(不过,在单个属性上使用读/写锁通常有点夸张。它们最好在更高的层次上应用。一个简单的锁在这里通常就足够了,因为考虑到持有锁的时间,争用的可能性可能非常小,并且获取读/写锁比简单的锁更昂贵)。

票数 12
EN

Stack Overflow用户

发布于 2008-11-10 19:52:05

考虑到两种解决方案都不好的可能性,因为它们掩盖了异常。

没有catchtry显然不是一个好主意;有关using语句同样危险的原因,请参阅MSDN

另请注意,微软现在建议使用ReaderWriterLockSlim而不是ReaderWriterLock。

最后,请注意,微软示例使用了两个try-catch块来避免这些问题,例如

代码语言:javascript
复制
try
{
    try
    {
         //Reader-writer lock stuff
    }
    finally
    {
         //Release lock
    }
 }
 catch(Exception ex)
 {
    //Do something with exception
 }

一个简单,一致,干净的解决方案是一个很好的目标,但是假设你不能仅仅使用lock(this){return mydateetc;},你可能会重新考虑这种方法;如果有更多的信息,我相信Stack Overflow可以有所帮助;-)

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/278902

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档