我有一个包含整数ID值的文件。目前读取该文件与ReaderWriterLockSlim
保护这样:如何制作只允许一个线程从资源读取的锁定?
public int GetId()
{
_fileLock.EnterUpgradeableReadLock();
int id = 0;
try {
if(!File.Exists(_filePath))
CreateIdentityFile();
FileStream readStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(readStream);
string line = sr.ReadLine();
sr.Close();
readStream.Close();
id = int.Parse(line);
return int.Parse(line);
}
finally {
SaveNextId(id); // increment the id
_fileLock.ExitUpgradeableReadLock();
}
}
的问题是,GetId()
后后续行动可能会失败。正如你所看到的,GetId()
方法每次都会增加ID,不管发出ID后会发生什么。发布的ID可能会被挂起(如上所述,可能会发生异常)。随着ID增加,一些ID可能未被使用。
所以我想移动SaveNextId(id)
,删除它(SaveNextId()
实际上也使用锁,除了它是EnterWriteLock
)。在完成所有必需的方法执行后,从外部手动调用它。这带来了另一个问题 - 在执行SaveNextId()
之前,多个线程可能会输入GetId()
方法,并且它们可能都会收到相同的ID。
我不希望任何解决方案,在操作后必须更改ID,并以任何方式纠正它们,因为这样做不好,可能会导致更多问题。
我需要一个解决方案,我可以以某种方式回调到FileIdentityManager(这是处理这些ID的类),并让管理员知道它可以执行保存下一个ID然后释放包含文件的读锁定ID。
Essentialy我想复制关系数据库的自动增量行为 - 如果在行插入过程中出现任何错误,这个ID不被使用,它仍然可以使用,但它也不会发生相同的ID发出。希望这个问题是可以理解的不足,为您提供一些解决办法..
UPDATE:请参见注释给答案有关行为的详细信息我想
我认为你有非顺序的ID是一件坏事吗? – Chris
如果你想要一个只允许一个线程的锁,为什么不使用'lock'?我只是阅读标题而不是问题! –
我会处理因删除而发生的问题。但我不想把它们浪费在没有成功的文件保存上,没有成功的类型转换等等。我现在就开始工作了,但这个非序列ID问题很快就显示出来了,因为ID暴露在UI中,它看起来很难看。两个并发内容项目可能具有相隔10个数字或更多的ID。 – mare