C # заблокировать каждый объект в коллекции перед выполнением действия - PullRequest
0 голосов
/ 30 октября 2019

У меня есть коллекция объектов:

List<SubscriptionSeat> seatsToRemove;

Каждый объект SubscriptionSeat имеет метод GetModifyLock() для блокировки его в распределенной среде перед внесением в него каких-либо изменений. Используется следующим образом:

var seatToRemove = seatsToRemove[0];
using(seatToRemove.GetModifyLock())
{
    seatToRemove.HardDelete();
}

Я хочу выполнить действие для каждого объекта в seatsToRemove, но я хочу получить все их блокировки до выполнения действия. Является ли оператор блока try, finally самым безопасным способом сделать это, чтобы убедиться, что все блокировки расположены правильно и что действие выполняется только после получения всех блокировок?

var objLocks = new List<DistributedLock>();
try
{
    // Obtain locks
    foreach (var seatToRemove in seatsToRemove)
    {
        objLocks.Add(seatToRemove.GetModifyLock());
    }

    // Perform locked actions
    foreach (var seatToRemove in seatsToRemove)
    {
        seatToRemove.HardDelete();
    }
}
finally
{
    // Clean up
    foreach (var objLock in objLocks)
    {
        objLock.Dispose();
    }
}

1 Ответ

0 голосов
/ 30 октября 2019

Ваш подход может вызвать необработанные исключения. Чтобы сделать его более надежным, вы можете создать одноразовый список и обработать исключение там.

using (var objLocks = new DisposableList<DistributedLock>())
{
    // Obtain locks
    foreach (var seatToRemove in seatsToRemove)
    {
        objLocks.Add(seatToRemove.GetModifyLock());
    }

    // Perform locked actions
    foreach (var seatToRemove in seatsToRemove)
    {
        seatToRemove.HardDelete();
    }
}

DisposableList

public class DisposableList<T> : List<T>, IDisposable
{
    public void Dispose()
    {
        foreach (T item in this)
        {
            try
            {
                IDisposable disposableItem = item as IDisposable;
                if (disposableItem != null)
                {
                    disposableItem.Dispose();
                }
            }
            catch (Exception ex)
            {
                ///Log and do something
            }
        }
        this.Clear();
        this.TrimExcess();
    }
}
...