如何在VS2012中获取多个锁而不会弄乱缩进

时间:2014-11-12 20:47:53

标签: c# visual-studio visual-studio-2012 auto-indent

这看起来像一个愚蠢的问题,但我无法找到解决方案。

我的问题是C#不允许在单个lock语句中获取多个锁。这不会起作用:

lock (a, b, c, d)
{
    // ...
}

相反,为了做到这一点,似乎需要一些疯狂的缩进:

lock (a)
    lock (b)
        lock (c)
            lock (d)
            {
                // ...
            }

与代码已经存在的所有其他缩进级别(命名空间,类,方法,条件,循环......)相结合,这会变得疯狂。所以相反,我想使用这种格式:

lock (a) lock (b) lock (c) lock (d)
{
    // ...
}

并保持我的理智。但Visual Studio(我使用的是2012年)却没有听说过它。一旦我输入任何右括号,上面就变成了愚蠢的东西,如:

lock (a) lock (b) lock (c) lock (d)
                  {
                      // ...
                  }

似乎我无能为力。有没有办法让这项工作?

3 个答案:

答案 0 :(得分:2)

只是一个想法: - )

static class LockAndExecute
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    static void _gen(Action a, object[] objs, int i = 0){

        bool lockWasTaken = false;
        var temp = objs[i];
        try { 
            Monitor.Enter(temp, ref lockWasTaken); 
            if(i + 1 >= objs.Length) 
                a();
            else
                _gen(a, objs, i + 1);
        }
        finally 
        { 
            if (lockWasTaken) 
                Monitor.Exit(temp); 
        }
    }

    public static void Do(object[] objectsToLock, Action action){
            _gen(action, objectsToLock);
    }
}

和用法;

LockAndExecute.Do(new[]{a, b}, () => {
    Console.WriteLine("Eww!");
});

答案 1 :(得分:1)

一次使用那么多锁只是要求死锁。哎呀,即使一次获得两个不同的锁也存在这种风险。

至少,你应该非常非常小心,只能按照完全相同的顺序获取这些锁,而不是一次获得多个锁。

此外,“好格式化”在旁观者的眼中。也就是说,每个人都有自己最好的想法。但是,除非你特别要求(例如通过触发自动格式规则或明确地自动格式化),否则以下内容应该可以正常工作,而不会与VS混淆:

lock (a)
lock (b)
lock (c)
lock (d)
{
}

您也可以将这种方法与using语句一起使用(连续使用多个语句的情况更为常见),VS IDE已经预料到了这种情况。

答案 2 :(得分:0)

您可以通过更改代码来解决IDE的烦人行为,尽管更改代码以解决IDE行为的想法使我的良心有些痛苦。如果这是一个玩具项目,我会这样做,但不会考虑其他开发人员可能会从事的严肃工作。

使用IDisposable实现来实现锁。 using语句没有lock语句那样令人讨厌的缩进问题。

class myLock : IDisposable
{
    private object _obj;

    public myLock(object obj)
    {
        _obj = obj;
        System.Threading.Monitor.Enter(obj);
    }

    public void Dispose()
    {
        System.Threading.Monitor.Exit(_obj);
        _obj = null;
    }

    public static void example()
    {
        var obj1 = new object();
        var obj2 = new object();
        var obj3 = new object();

        lock (obj1)
            lock (obj2)
                lock (obj3)
                {
                    // Stupid indentation >:(
                }

        using (new myLock(obj1))
        using (new myLock(obj2))
        using (new myLock(obj3))
        {
            // Ahhhh... :-)
        }
    }
}