我怎样才能优雅地写出锁{}?

时间:2010-12-24 05:25:24

标签: c# multithreading locking

在我的多线程项目(C#3.5)中,我有许多与此类似的代码:

    Map map;
    lock ( _maps )
    {
        map = _maps.First( i => i.ID == arg.MapID );
    }

对我来说看起来很难看。采用太多行进行简单检索......

我想要的是一个简单的行代码:

    Map map = _maps.First( i => i.ID == arg.MapID );

但有锁:(不工作)

    Map map = lock( _maps ){ _maps.First( i => i.ID == arg.MapID ) };

    Map map = delegate(){ lock( _maps ) return _maps.First( i => i.ID == arg.MapID ) };

任何帮助将不胜感激:) 感谢

8 个答案:

答案 0 :(得分:3)

public T Lock<T>(object o, Func<T> f) {
    lock (o) {
        return f();
    }
}

...

Map map = Lock(_maps, () => _maps.First(i => i.ID == arg.MapID));

答案 1 :(得分:3)

更好的是,只需在Object而不是IEnumerable<T>上制作扩展方法:

public static T LockAndExecute<T>(this Object obj, Func<T> operation)
{
    lock(obj)
    {
        return operation();
    }
}

这样不仅是你的情况优雅

Map map = _maps.LockAndExecute(() =>  _maps.First(i => i.ID == arg.MapID);

但无论你在锁内做什么,都可以重复使用。

答案 2 :(得分:1)

如果你觉得它在一行上看起来更好,

Map map; lock( _maps ){ map = _maps.First( i => i.ID == arg.MapID ) }; 

只是你试过的4个字符。但它与你现在拥有的相同,只是在一条线上。

答案 3 :(得分:1)

你可以使用扩展方法......

public static TResult Lock<T, TResult>(this T arg, 
     Func<T, TResult> callback) where T : class
{
    if(arg == null) throw new ArgumentNullException();

    lock(arg)
    {
        return callback(arg);
    }
}

你可以像这样使用它

Map map = maps.Lock(x => x.First( i => i.ID == arg.MapID ));

答案 4 :(得分:1)

使用这样的函数:

static class WithLock
{
    public static T Execute<T>(object o, Func<T> action)
    {
        lock (o)
        {
            return action();
        }
    }
}

你可以这样做:

Map map = WithLock.Execute(_maps, () => _maps.First( i => i.ID == arg.MapID ));

答案 5 :(得分:0)

丑?我不这么认为。也许你可以使用它,它们完全相同。

Monitor.Enter(obj);
try
{
   //do something
}
finally
{
   Monitor.Exit(obj);
}

但我更喜欢lock语句,因为{}提供了更清晰的范围。

lock(obj)
{
   //body of the lock statement
}//end of the lock scope

它更清晰,不是吗?为什么你觉得它难看?

答案 6 :(得分:0)

在没有扩展方法的情况下尝试简单的事情

private static readonly object lockObj = new object();
private static T LockAndExecute<T>(Func<T> func)
{
    lock (lockObj)
        return func();
}

Map map = LockAndExecute(() => _maps.First(i => i.ID == arg.MapID));

答案 7 :(得分:0)

我真的不喜欢其他答案中提供的任何选项。所提出的方法依赖于调用者理解方法的内部,并且调用站点复杂度对于方法想要做的事情来说太高了。这些都是主要的代码味道。

相反,为什么不在正确的抽象层次上创建明显的方法呢?然后,您的代码将转到一个简单的行,它将重要。

private Map GetMapById(int id)
{
    lock (_maps)
    {
        return _maps.First( i => i.ID == id );
    }
}

....    

Map map = GetMapById(arg.MapID);