Асинхронные методы с или без ConfigureAwait в NetStandard lib для Net Core
У меня есть библиотека, которая делает массовую вставку.
Библиотека является расширением EfCore, созданным в.NetStandard(1.4), поэтому ее можно использовать в проектах ASP.NET Core, ориентированных как на.NetCore(1.0+), так и на полную версию NetFramework(4.6.1+).
Одна из функций:
public static BulkInsert<T>(this DbContext context, IList<T> entities)
{
SqlBulkOperation.InsertAsync<T>(context, entities);
}
internal static class SqlBulkOperation
{
public static void Insert<T>(DbContext context, IList<T> entities)
{
....
sqlBulkCopy.WriteToServer(reader);
....
}
}
Далее я добавил тот же метод с поддержкой асинхронного
public static async Task BulkInsertAsync<T>(this DbContext context, IList<T> entities)
{
await SqlBulkOperation.InsertAsync<T>(context, entities, null, null);
}
internal static class SqlBulkOperation
{
public static async Task InsertAsync<T>(DbContext context, IList<T> entities)
{
....
await sqlBulkCopy.WriteToServer(reader);
....
}
}
И теперь мне посоветовали изменить асинхронный метод таким образом, чтобы добавить ConfigureAwait(false) к внутреннему методу, а также оптимизировать простую асинхронность, удалив явное ключевое слово async из открытого метода следующим образом:
public static Task BulkInsertAsync<T>(this DbContext context, IList<T> entities)
{
return SqlBulkOperation.InsertAsync<T>(context, entities, null, null, true);
}
internal static class SqlBulkOperation
{
public static async Task InsertAsync<T>(DbContext context, IList<T> entities)
{
await sqlBulkCopy.WriteToServerAsync(reader).ConfigureAwait(false);
}
}
Итак, вопрос таков:
В этой ситуации лучше использовать ConfigureAwait(false)?
А во-вторых, целесообразно ли удалять ключевое слово async из открытых методов для сценария в примере?
PS Я уже прочитал несколько блогов и несколько вопросов здесь относительно этой проблемы, но все еще не пришел к окончательному ответу. Я читал, что у ASP.NET Core больше нет "контекста", поэтому, принимая это во внимание, какой будет наилучшая практика здесь?
1 ответ
В этой ситуации лучше использовать ConfigureAwait(false)?
Я вообще рекомендую ConfigureAwait(false)
для библиотечного кода. Тот же совет от почти полувековой давности до сих пор применяется сегодня. Однако здесь есть несколько смягчающих факторов:
- Ваши единственные целевые платформы не предоставляют
SynchronizationContext
, Таким образом, пока ваш код работает только на этих платформах,ConfigureAwait(false)
не обязательно - Обе команды ASP.NET Core и EF Core больше не используют
ConfigureAwait(false)
, Тем не менее, обратите внимание, что команда EF Core предоставляет синхронные API, поэтому идея заключается в том, что люди не будут блокировать свой асинхронный код, поэтому отсутствиеConfigureAwait(false)
не будет вызывать тупик при использовании на платформах сSynchronizationContext
,
Так что, в вашем случае, вы можете не включать ConfigureAwait(false)
, Я бы сказал, что это правильный подход, поскольку ваша библиотека является расширением для EFCore и поскольку вы предоставляете как синхронные, так и асинхронные API (как это делает EFCore). Имейте в виду, что это открывает тупики в сценарии, когда пользователь устанавливает на платформу с SynchronizationContext
(например, классический ASP.NET) и блоки вашего асинхронного кода. Но EFCore имеет такое же ограничение.
Кстати, попробуйте взломать логические аргументы, чтобы предотвратить дублирование кода в ваших парах синхронных / асинхронных методов.
А во-вторых, целесообразно ли удалять ключевое слово async из открытых методов для сценария в примере?
Я не уверен, почему это было бы рекомендовано. Это не позволяет конечным пользователям определить, используете ли вы async
ключевое слово (есть атрибут, который компилятор размещает на async
методы), но кого это волнует?