我有一个WCF服务和一个带有记录的资源(有ID来标识它们)。我想,只有1 ID可以同时访问 - 所以我写了一个小帮手资源:并发 - 每次编辑1个资源
public sealed class ConcurrencyIdManager
{
private static object _syncRootGrant = new object();
private static List<int> _IdsInUse = new List<int>();
... // singleton
public void RequestAndWaitForIdGrant(int id)
{
lock (_syncRootGrant)
{
while (_IdsInUse.Where(i => i == id).Count() != 0)
{
Monitor.Wait(_syncRootGrant);
}
_IdsInUse.Add(id);
}
}
public void ReleaseGrantForId(int id)
{
lock (_syncRootGrant)
{
_IdsInUse.Remove(id);
Monitor.PulseAll(_syncRootGrant);
}
}
所以在我的WCF服务,我有
public void UpdateMySpecialEntity(Entity foo)
{
ConcurrencyIdManager.Instance.RequestAndWaitForIdGrant(foo.Id);
try {
// do something with the entity foo
}
finally { ConcurrencyIdManager.Instance.ReleaseGrantForId(foo.Id); }
}
是实施正确的那么远? :-)
如果我看了你的代码正确,你不跟1个资源在同一时间工作,你允许最多一个线程在任何给定时间对资源工作。每个资源只有一个可锁定的对象会不会更容易? – 2012-01-14 11:44:28
我试图完成的任务是: *它应该被允许用多个线程更新具有不同ID的多个实体 *它不应该被允许用ID X同时更新一个实体。 我不太清楚“每个资源的可锁定对象”是什么意思?如果你的意思是每个资源项目 - 这是不可能的,因为数量是无限的(在这种情况下,假定资源是数据库) – damike 2012-01-14 12:08:44
您正在使用哪个版本的.NET?你有权访问ConcurrentBag?此外,这段代码将阻止对列表的整个访问,不仅限于特定的ID,所以不需要使用Wait和Pulse进行额外的阻塞。 –
oleksii
2012-01-14 12:29:49