Вот сценарий:
У меня есть объект с именем Transaction
, который должен убедиться, что только один объект имеет право редактировать его в любой момент времени.
Чтобы упростить долговременную блокировку, у меня есть класс, генерирующий объект токена, который можно использовать для внесения изменений.
Вы бы использовали это так:
var transaction = new Transaction();
using (var tlock = transaction.Lock())
{
transaction.Update(data, tlock);
}
Теперь я хочу, чтобы класс TransactionLock
реализовал IDisposable
, чтобы его использование было понятно. Но у меня нет никаких неуправляемых ресурсов, чтобы распоряжаться. однако сам объект TransctionLock является своего рода «неуправляемым ресурсом» в том смысле, что CLR не знает, как его правильно завершить.
Все это было бы хорошо, я бы просто использовал IDisposable
и покончил бы с этим.
Однако моя проблема возникает, когда я пытаюсь сделать это в финализаторе:
~TransactionLock()
{
this.Dispose(false);
}
Я хочу, чтобы финализатор освободил транзакцию из блокировки, если это возможно. Как в финализаторе определить, завершена ли родительская транзакция (this.transaction
)?
Есть ли лучший шаблон, который я должен использовать?
Кроме того, сам класс Transaction
не должен быть одноразовым, поскольку он не поддерживает ссылку на замок и не заботится о том, разблокирован ли он или нет, когда он уходит в могилу.
<Ч />
Класс Transaction выглядит примерно так:
public sealed class Transaction
{
private readonly object lockMutex = new object();
private TransactionLock currentLock;
public TransactionLock Lock()
{
lock (this.lockMutex)
{
if (this.currentLock != null)
throw new InvalidOperationException(/* ... */);
this.currentLock = new TransactionLock(this);
return this.currentLock;
}
}
public void Update(object data, TransactionLock tlock)
{
lock (this.lockMutex)
{
this.ValidateLock(tlock);
// ...
}
}
internal void ValidateLock(TransactionLock tlock)
{
if (this.currentLock == null)
throw new InvalidOperationException(/* ... */);
if (this.currentLock != tlock)
throw new InvalidOperationException(/* ... */);
}
internal void Unlock(TransactionLock tlock)
{
lock (this.lockMutex)
{
this.ValidateLock(tlock);
this.currentLock = null;
}
}
}
И Dispose(bool)
код для TransactionLock
:
private void Dispose(bool disposing)
{
if (disposing)
{
if (this.Transaction != null)
{
this.Transaction.Unlock(this);
this.Transaction = null;
}
}
}