Подтвердить что ты не робот

Отказоустойчивое удаление в асинхронном мире

В синхронном мире С# делает управление всеми вещами достаточно простым:

using(IDisposable someDisposable=bla.bla())
{
     //do our bidding
}
//don't worry too much about it

Однако, когда мы ищем async, у нас больше нет удобства блока using. Одна из лучших стратегий, с которыми я столкнулся, это CCR iterator, который позволяет нам использовать асинхронный код "как если бы он был синхронным". Это означает, что мы можем сохранить наш блок using в обработчике итератора и не слишком увязнуть в сложном решении, когда нужно распоряжаться и ловить все случаи, когда требуется удаление.

Однако во многих случаях вызов CCR может показаться излишним, и, если честно, хотя мне вполне комфортно с CCR, непосвященному он может выглядеть как двуствольный.

Итак, мой вопрос: какие существуют другие стратегии для управления одним IDisposable, когда одноразовые объекты должны сохраняться за пределами непосредственной области?

4b9b3361

Ответ 1

Оказывается, эта проблема была также умом дизайнеров языка.

Правильный ответ на этот вопрос теперь заключается в использовании версий асинхронных API, основанных на Task, которые были предоставлены практически для всех асинхронных операций в сочетании с новыми ключевыми словами С# async/await. Это позволяет нам держать все в объеме в течение всего времени асинхронных операций:

async Task<int> DoSomething()
{
    using(var foo = new SomeDisposableThing())
    {
         await foo.DoSomethingAsync();
    }
    return 0;
}

Ответ 2

Один из подходов состоит в том, чтобы все методы, которые не могли бы сосуществовать с методом удаления, блокировать во время их запуска и проверять очередь на объекты, нуждающиеся в удалении, когда они заканчиваются. Затем метод удаления может добавить себя в очередь, использовать TryEnter, чтобы попытаться получить блокировку, удалить объект и удалить его из очереди в случае успеха, иначе пусть текущий держатель блокировки обработает распоряжение.