Asynchronous 在NetCore的NetStandard库上使用或不使用ConfigureAwait的异步方法

Asynchronous 在NetCore的NetStandard库上使用或不使用ConfigureAwait的异步方法,asynchronous,asp.net-core,async-await,configureawait,Asynchronous,Asp.net Core,Async Await,Configureawait,我有一个正在进行批量插入的库。 库是在.NetStandard(1.4)中进行的EfCore扩展,因此它可以用于针对.NetCore(1.0+)或完整NetFramework(4.6.1+)的ASP.NET核心项目 其中一项功能是: public static BulkInsert<T>(this DbContext context, IList<T> entities) { SqlBulkOperation.InsertAsync<T>(contex

我有一个正在进行批量插入的库。
库是在.NetStandard(1.4)中进行的EfCore扩展,因此它可以用于针对.NetCore(1.0+)或完整NetFramework(4.6.1+)的ASP.NET核心项目
其中一项功能是:

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);
        ....
    }
}
publicstaticbulkinsert(此DbContext上下文,IList实体)
{
InsertAsync(上下文、实体);
}
内部静态类操作
{
公共静态void插入(DbContext上下文,IList实体)
{
....
sqlBulkCopy.WriteToServer(读卡器);
....
}
}
接下来,我添加了支持async的相同方法

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);
        ....
    }
}
公共静态异步任务BulkInsertAsync(此DbContext上下文,IList实体)
{
等待SqlBulkOperation.InsertAsync(上下文、实体、null、null);
}
内部静态类操作
{
公共静态异步任务InsertAsync(DbContext上下文,IList实体)
{
....
等待sqlBulkCopy.WriteToServer(读卡器);
....
}
}
现在,有人建议我更改async方法,将ConfigureAwait(false)添加到内部方法中,并通过从公开方法中删除显式async关键字来优化简单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);
    }
}
公共静态任务BulkInsertAsync(此DbContext上下文,IList实体)
{
返回SqlBulkOperation.InsertAsync(上下文、实体、null、null、true);
}
内部静态类操作
{
公共静态异步任务InsertAsync(DbContext上下文,IList实体)
{
等待sqlBulkCopy.WriteToServerAsync(读卡器).ConfigureWait(false);
}
}
所以问题是:
在这种情况下,是否最好使用ConfigureWait(false)?
第二,从示例中场景的公开方法中删除async关键字是否可取

PS我已经读了一些博客和一些关于这些问题的问题,但仍然没有得出结论性的答案。 我读到ASP.NET核心不再有“上下文”,因此考虑到这一点,这里的最佳实践是什么

在这种情况下,使用ConfigureWait(false)是否更好

对于库代码,我通常建议使用
ConfigureAwait(false)
。然而,这里有一些缓解因素:

  • 您唯一的目标平台不提供同步上下文。因此,只要代码只在这些平台上运行,
    ConfigureAwait(false)
    就没有必要了
  • ASP.NET核心和。但是,请注意,EF核心团队确实提供了同步API,因此其想法是人们不会首先阻塞异步代码,因此在具有
    SynchronizationContext
    的平台上使用时,缺少
    ConfigureAwait(false)
    不会导致死锁
因此,在您的情况下,您可以选择不包括
ConfigureAwait(false)
。我认为这是一种有效的方法,因为您的库是EFCore的扩展,而且您提供的是同步和异步api(就像EFCore一样)。请记住,当用户安装到带有
SynchronizationContext
(例如,经典ASP.NET)的平台上并在异步代码上阻塞时,这会打开死锁。但EFCore也有同样的局限性

在旁注上,尝试一下

第二,从示例中场景的公开方法中删除async关键字是否可取

不,我不知道为什么会推荐这个。它阻止最终用户检测您是否正在使用
async
关键字(编译器在
async
方法上放置了一个属性),但谁在乎呢

在这种情况下,使用ConfigureWait(false)是否更好

对于库代码,我通常建议使用
ConfigureAwait(false)
。然而,这里有一些缓解因素:

  • 您唯一的目标平台不提供同步上下文。因此,只要代码只在这些平台上运行,
    ConfigureAwait(false)
    就没有必要了
  • ASP.NET核心和。但是,请注意,EF核心团队确实提供了同步API,因此其想法是人们不会首先阻塞异步代码,因此在具有
    SynchronizationContext
    的平台上使用时,缺少
    ConfigureAwait(false)
    不会导致死锁
因此,在您的情况下,您可以选择不包括
ConfigureAwait(false)
。我认为这是一种有效的方法,因为您的库是EFCore的扩展,而且您提供的是同步和异步api(就像EFCore一样)。请记住,当用户安装到带有
SynchronizationContext
(例如,经典ASP.NET)的平台上并在异步代码上阻塞时,这会打开死锁。但EFCore也有同样的局限性

在旁注上,尝试一下

第二,从示例中场景的公开方法中删除async关键字是否可取


不,我不知道为什么会推荐这个。它阻止最终用户检测您是否使用了
async
关键字(编译器在
async
方法上放置了一个属性),但谁在乎呢?

这已经被问了100次了,答案总是一样的:在类库中总是使用
。ConfigureAwait(false)
,在WPF/Console/ASP.NET/ASP.NET核心项目中,永远不要使用它,第二个问题呢,删除async?@borisdj只有在需要继续时才使用wait,否则只返回任务。换句话说,如果调用任务后不需要任务的结果,则无需等待。只需返回任务。
BulkInsertAsync
中的async不是必需的,因此它可以正常工作。也没有
.configurewait
必要,因为您正在通过