В синхронной среде легко создать контекст с ограниченной областью действия, который позволит вам присоединить внешний контекст к текущему потоку. Примерами этого являются текущий TransactionScope или статический контекст ведения журнала потока.
using (new MyContext(5))
Assert.Equal(5, MyContext.Current);
Assert.Equal(null, MyContext.Current);
Контекст легко реализовать с помощью комбинации IDisposable и поля, статического для потока.
Очевидно, что при использовании асинхронных методов это не работает, потому что контекст основан на статическом поле потока. Итак, это не удается:
using (new MyContext(5))
{
Assert.Equal(5, MyContext.Current);
await DoSomethingAsync();
Assert.Equal(5, MyContext.Current);
}
И, конечно, мы также хотели бы, чтобы контекст передавался асинхронным методам в цепочке вызовов, так что это тоже должно работать:
using (new MyContext(5))
{
Assert.Equal(5, MyContext.Current);
await AssertContextIs(5);
}
У кого-нибудь есть идеи, как это можно реализовать? Потеря внеполосного контекста при использовании шаблона async/await делает некоторые фрагменты кода действительно уродливыми.
Подумайте об асинхронных вызовах WebAPI, когда вы хотели бы использовать контекст на основе запроса для целей ведения журнала. Вы хотите, чтобы ваш регистратор глубоко в стеке вызовов знал об идентификаторе запроса без необходимости передавать этот идентификатор запроса через стек вызовов с использованием параметров.
Спасибо за любую помощь!
using
заявления после того, как выawait DoSomethingAsync
. - person Yuval Itzchakov   schedule 24.09.2014