Асинхронные методы с или без 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 методы), но кого это волнует?

Другие вопросы по тегам