Являются ли примитивы синхронизации бесполезными в TransactionScopes с асинхронными / ожидающими вызовами?
Я считаю, что все примитивы синхронизации на основе потоков бесполезны в неявных транзакциях. Учитывая класс:
public class Country : IEnlistNotification
{
public ReaderWriterLockSlim Lock { get; } = new ReaderWriterLockSlim();
public void Commit(Enlistment enlistment)
{
this.Lock.ExitWriteLock();
}
}
У меня есть следующий код:
using (TransactionScope transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
Country country = new Country();
Transaction.Current.EnlistVolatile(country, EnlistmentOptions.None);
country.Lock.EnterWriteLock();
await dbContext.Countries.AddAsync(newCountry).ConfigureAwait(true);
await dbContext.SaveChangesAsync().ConfigureAwait(true);
transactionScope.Complete();
}
Проблема в том, что даже при использовании ConfigureAwait (true) вы не гарантированно вернетесь в том же потоке. Таким образом, хотя транзакция может завершиться в другом потоке, когда она вызывает методы Commit или Rollback для энергозависимых ресурсов и пора выходить из блокировок, она (часто) находится в другом потоке, нежели когда вы ввели блокировку.
Нет абсолютно никакого способа снять блокировку, и вы скоро зашли в тупик. Похоже, что ReaderWriterLockSlim и остальные примитивы довольно бесполезны в архитектуре, использующей шаблон асинхронности / ожидания. Я что-то упускаю из виду?