ASP.NET核心MemoryCache异步的GetOrCreateAsync开销并等待

时间:2018-06-18 13:36:22

标签: c# asynchronous asp.net-core async-await

首先介绍一下背景:

目前,我们正在使用ASP.NET Core MemoryCache MemoryCache Doc

IMemoryCache界面上有一个名为GetOrCreateAsync(...)的方法,我可以传入工厂函数Func<ICacheEntry, Task<TItem>> factory

由于这是一个异步方法签名,我必须一直实现async await(有时是大约8个方法的callstack),即使缓存命中本身是同步的。在我的场景中,我按每个请求大约200-2500次点击缓存。有些参赛作品我每隔60分钟就会刷新一次。

现在的问题是:

我目前的理解是,.NET Core必须为每个调用创建一个状态机,即使我只是以同步的方式命中缓存,因为它的方法签名。你们其中一个人知道这有多大的开销吗?创建一个同步工厂(这是一个Web-API调用)会有一些阻塞更有意义,以便我可以使用GetOrCreate(...)吗?或许你们中的一些人有完全不同的想法。

希望你明白我的痛点。

1 个答案:

答案 0 :(得分:-1)

这里有很多混淆。首先也是最重要的是,委托不是异步委托,而是任务返回委托。将两者混淆是典型的,因为您通常只从异步操作返回任务,但您不必这样做。为了满足代表的需要,您只需使用Task.FromResult(foo),其中foo是您最终返回的内容。重要的是,可以同步满足该返回,因此,如果基础进程是同步的,那么从此处开始就不需要涉及async / await。

其次,await默认会创建SynchronizationContext。这在线程切换的情况下存在,因为任何线程本地需要被移动到新线程以防止丢失引用。这涉及到向堆中添加内容,是的,可能会降低性能。但是,如果您不使用线程本地和/或没有线程切换的可能性,您就不需要这样做。在这种情况下,您可以在异步方法上调用ConfigureAwait(false)。特别是ASP.NET Core根本不使用线程局部化(通过依赖注入来满足交叉依赖性)。因此,使用ConfigureAwait(false)总是是安全的,您应该将其添加到您执行的每个异步操作中。在这种特殊情况下,SynchronizationContext是无用的,因为您的操作是同步的,这意味着无论如何都不会发生线程切换。