在我的多线程项目(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 ) };
任何帮助将不胜感激:) 感谢
答案 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);