1 Вопрос: Контекст теряется при переназначении Transaction.Current в асинхронный / ожидающий код

вопрос создан в Thu, May 2, 2019 12:00 AM

При переназначении Transaction.Current я, похоже, теряю исходное поведение TransactionScopeAsyncFlowOption моего TransactionScope. Код после второго await теряет значение Transaction.Current.

Пример кода (Linqpad):

async Task Main()
{
    Thread.CurrentThread.ManagedThreadId.Dump("before await");
    var scope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
    var transaction = Transaction.Current;

    await Task.Delay(1000).ConfigureAwait(false);

    Thread.CurrentThread.ManagedThreadId.Dump("after first await");
    Transaction.Current = transaction;
    Transaction.Current.Dump(); // not null

    await Task.Delay(1000).ConfigureAwait(false);

    Thread.CurrentThread.ManagedThreadId.Dump("after second await");
    Transaction.Current.Dump(); // is null :/
}

Я знаю Мне следует использовать оператор using для TransactionScope, а не переназначать внешнюю транзакцию, однако по причинам это невозможно. Мне любопытно узнать причину поведения приведенного выше фрагмента, и мне интересно, есть ли способы сохранить исходное поведение TransactionScopeAsyncFlowOption.

    
4
  1. Где вы запускаете этот код? Я попытался LINQPad и, если я не установил Transaction.Current, я всегда получаю одну и ту же транзакцию.
    2019-05-02 17: 30: 28Z
  2. Похоже, что реализация метода установки для Transaction.Current всегда использует контекст TLS, а не контекст async-compatbile. Реализация конструктора TransactionScope (в частности, PushScope) устанавливает один из них. Похоже, вам придется открыть отчет об ошибке.
    2019-05-02 20: 00: 34Z
  3. Соответствующий отчет об ошибке в dotnet /corefx можно найти здесь .
    2019-05-03 13: 28: 36Z
1 ответ                              1                         

Мне удалось устранить проблему, обернув объект Transaction в другой объект TransactionScope с включенным TransactionScopeAsyncFlowOption:

async Task Main()
{
    var scope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
    var transaction = Transaction.Current;

    await Task.Delay(1000);

    Transaction.Current = transaction;
    Debug.Assert(Transaction.Current != null); // not null

    await Task.Delay(1000);

    Debug.Assert(Transaction.Current == null); // is null :/

    using (var innerScope = new TransactionScope(transaction, TransactionScopeAsyncFlowOption.Enabled))
    {
        // Transaction.Current state is kept across async continuations
        Debug.Assert(Transaction.Current != null); // not null
        await Task.Delay(10);
        Debug.Assert(Transaction.Current != null); // not null
        innerScope.Complete();
    }
}
    
1
2019-05-06 08: 19: 59Z
  1. Отлично! И вы отправили свое исправление в виде запроса на извлечение, которое я принял и опубликовал как Rebus.TransactionScopes 5.0.0-b2 - спасибо! 😎
    2019-05-06 08: 43: 53Z
источник размещен Вот