'using'语句vs'finally try'

问题描述 投票:74回答:15

我有很多属性,将要使用读/写锁。我可以使用try finallyusing子句来实现它们。

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();
    }
}

我有很多属性,将要使用读/写锁。我可以通过try try或using子句来实现它们。在最后的尝试中,我将在...

c# .net multithreading using-statement
15个回答
87
投票

0
投票
我有一个与您非常相似的模型,只有一个例外。我定义了一个基本接口ILock,并在其中提供了一种称为Acquire()的方法。 Acquire()方法返回IDisposable对象,结果意味着只要我要处理的对象的类型为ILock,它就可以用于执行锁定范围。为什么这很重要?

0
投票
class StackOTest { private delegate DateTime ReadLockMethod(); private delegate void WriteLockMethod(); static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock(); private DateTime dtMyDateTime_m; public DateTime MyDateTime { get { return ReadLockedMethod( rwlMyLock_m, delegate () { return dtMyDateTime_m; } ); } set { WriteLockedMethod( rwlMyLock_m, delegate () { dtMyDateTime_m = value; } ); } } private static DateTime ReadLockedMethod( ReaderWriterLock rwl, ReadLockMethod method ) { rwl.AcquireReaderLock(0); try { return method(); } finally { rwl.ReleaseReaderLock(); } } private static void WriteLockedMethod( ReaderWriterLock rwl, WriteLockMethod method ) { rwl.AcquireWriterLock(0); try { method(); } finally { rwl.ReleaseWriterLock(); } } }

0
投票
在任何情况下,以前的版本都不能很好地用于一般用途,因为读取锁始终需要返回值。这样可以解决:

class StackOTest { static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock(); private DateTime dtMyDateTime_m; public DateTime MyDateTime { get { DateTime retval = default(DateTime); ReadLockedMethod( delegate () { retval = dtMyDateTime_m; } ); return retval; } set { WriteLockedMethod( delegate () { dtMyDateTime_m = value; } ); } } private void ReadLockedMethod(Action method) { rwlMyLock_m.AcquireReaderLock(0); try { method(); } finally { rwlMyLock_m.ReleaseReaderLock(); } } private void WriteLockedMethod(Action method) { rwlMyLock_m.AcquireWriterLock(0); try { method(); } finally { rwlMyLock_m.ReleaseWriterLock(); } } }


0
投票
var rwlock = new ReaderWriterLockSlim(); using (var l = rwlock.ReadLock()) { // read data } using (var l = rwlock.WriteLock()) { // write data }

这里是代码:


0
投票
然后,您将实现“从苹果到苹果”的实现(和MSIL)(两种解决方案的MSIL都相同)。使用using可能仍然是一个好主意,因为增加了作用域,并且框架将确保IDisposable的正确使用(如果您自己实现IDisposable,则后者的好处较小)。

-1
投票
class StackOTest { private delegate DateTime ReadLockMethod(); private delegate void WriteLockMethod(); static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock(); private DateTime dtMyDateTime_m; public DateTime MyDateTime { get { return ReadLockedMethod( delegate () { return dtMyDateTime_m; } ); } set { WriteLockedMethod( delegate () { dtMyDateTime_m = value; } ); } } private DateTime ReadLockedMethod(ReadLockMethod method) { rwlMyLock_m.AcquireReaderLock(0); try { return method(); } finally { rwlMyLock_m.ReleaseReaderLock(); } } private void WriteLockedMethod(WriteLockMethod method) { rwlMyLock_m.AcquireWriterLock(0); try { method(); } finally { rwlMyLock_m.ReleaseWriterLock(); } } }

12
投票
我绝对喜欢第二种方法。使用时更简洁,更不易出错。

8
投票
考虑两种解决方案都不好的可能性,因为

它们的掩码例外


5
投票
我个人尽可能多地使用C#“ using”语句,但是为了避免潜在的问题,我还做了一些特定的事情。举例说明:

4
投票
我喜欢第三个选项

4
投票
“属性束”并锁定在属性获取器和设置器级别上看起来是错误的。您的锁定太精细了。在大多数典型的对象用法中,您需要确保获得了一个锁,以同时访问一个属性。您的具体情况可能有所不同,但我对此表示怀疑。

4
投票

1
投票
对于读/写锁,try / catch可能是最有用的,但是您也可以同时使用两者,例如:

0
投票

属性中更简单易读的代码。

© www.soinside.com 2019 - 2024. All rights reserved.