簡體   English   中英

如何優雅地編寫鎖{}?

[英]how can I write lock {} elegantly?

在我的多線程項目(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 ) };

任何幫助將不勝感激:)謝謝

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

...

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

更好的是,只需對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);

但是無論您在鎖中做什么,都可以重用它。

如果您認為某一行看起來更好,

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

只是您嘗試過的另外4個字符。 但這與您當前擁有的相同,只是一行。

您可以使用擴展方法...

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

具有這樣的功能:

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

丑陋? 我不這么認為。 也許您可以改用它,它們是完全一樣的。

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

但我更喜歡lock語句,因為{}提供了更清晰的范圍。

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

更清楚了,不是嗎? 你為什么覺得丑?

嘗試一些沒有擴展方法的簡單操作

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

我真的不喜歡其他答案中提供的任何選項。 所提出的方法依賴於呼叫者對方法內部的了解,並且呼叫站點的復雜性對於該方法打算執行的操作而言太高了。 這兩個都是主要的代碼氣味。

相反,為什么不只是在正確的抽象級別上創建明顯的方法呢? 然后,您的代碼將下降到一條簡單的代碼行。

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

....    

Map map = GetMapById(arg.MapID);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM