我怎樣才能優雅地寫 lock {}? (how can I write lock {} elegantly?)


問題描述

我怎樣才能優雅地寫 lock {}? (how can I write lock {} elegantly?)

In my multi-threaded project(C# 3.5), I have many codes simliar to this:

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

It looks ugly to me. Takes too many lines for simple retrieval...

What I want is one line code as simple as this:

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

But with lock: (not working)

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

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

Any help will be greatly appreciated :) Thanks


參考解法

方法 1:

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

...

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

方法 2:

Better yet, just make an extension method on Object instead of IEnumerable<T>:

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

That way not only is your case elegant

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

but you can reuse this regardless of what you're doing within the lock.

方法 3:

If you think it looks better on one line,

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

is only another 4 characters to what you've tried.  But it's the same as what you currently have, just on one line.

方法 4:

you can use an extension method...

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

and you can use it like this

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

方法 5:

With a function like this:

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

you can do something like this:

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

(by VincentJ.D.Paul WheelerKirk BroadhurstaqwertGabe)

參考文件

  1. how can I write lock {} elegantly? (CC BY-SA 3.0/4.0)

#locking #multithreading #C#






相關問題

C# / ASP.NET - Web 應用程序鎖定 (C# / ASP.NET - Web Application locking)

在程序文件夾中創建鎖定文件會導致異常 (Creating Lock file in Programs Folder causes exception)

我什麼時候會使用 AutoResetEvent 和 ManualResetEvent 而不是 Monitor.Wait()/Monitor.Pulse()? (When would I use AutoResetEvent and ManualResetEvent instead of Monitor.Wait()/Monitor.Pulse()?)

鎖定一個 JavaScript 函數 (Lock a JavaScript Function)

當只有一個線程寫入共享變量時,我需要鎖嗎? (Do I need a lock when only a single thread writes to a shared variable?)

為什麼 lock(objLock) 比 lock(this) 好 (Why is it better to lock(objLock) than lock(this))

雙重檢查鎖定的修復有什麼問題? (What's wrong with this fix for double checked locking?)

在表格行上調用 Dibs (Calling Dibs on a table row)

我怎樣才能優雅地寫 lock {}? (how can I write lock {} elegantly?)

Double Check Lock 不能在這個 java 代碼上工作? (Doubly Check Lock Dosen't work on this java code?)

LINQPad / LINQ To SQL - 簡單查詢僅在循環內執行時才會引發內存不足 (LINQPad / LINQ To SQL - Simple Query Throws Out of Memory Only When Executed Inside a Loop)

如何在 dynamoDB 中實現 50 次寫入的事務? (How can I implement a transaction of 50 writes in dynamoDB?)







留言討論