这看起来像一个愚蠢的问题,但我无法找到解决方案。
我的问题是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)
{
// ...
}
似乎我无能为力。有没有办法让这项工作?
答案 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... :-)
}
}
}