C# ASP.NET核心内存缓存GetOrCreateAync异步和等待的开销

C# ASP.NET核心内存缓存GetOrCreateAync异步和等待的开销,c#,asynchronous,asp.net-core,async-await,C#,Asynchronous,Asp.net Core,Async Await,首先是一点背景: 目前,我们正在使用ASP.NET核心内存缓存 在IMemoryCache接口上有一个名为GetOrCreateAsync(…)的方法,我可以在其中传入一个工厂funcfunc工厂 因为这是一个异步方法签名,所以我必须一直实现async wait(有时是大约8个方法的调用堆栈),即使缓存命中本身是同步的。在我的场景中,每个请求大约命中缓存200-2500次。有些条目我必须每60分钟刷新一次,有些只是每天刷新一次 现在的问题是: 我目前的理解是,.NETCore必须为每个调用创建一

首先是一点背景:

目前,我们正在使用ASP.NET核心内存缓存

IMemoryCache
接口上有一个名为
GetOrCreateAsync(…)
的方法,我可以在其中传入一个工厂func
func工厂

因为这是一个异步方法签名,所以我必须一直实现
async wait
(有时是大约8个方法的调用堆栈),即使缓存命中本身是同步的。在我的场景中,每个请求大约命中缓存200-2500次。有些条目我必须每60分钟刷新一次,有些只是每天刷新一次

现在的问题是:

我目前的理解是,.NETCore必须为每个调用创建一个状态机,尽管我只是以同步方式命中缓存,因为它的方法签名。你们当中有人知道这件事的开销有多大吗?创建一个同步工厂(这是一个Web API调用)并加上一点阻塞,这样我就可以使用
GetOrCreate(…)
,这样做更有意义吗?或者你们中的一些人有完全不同的想法


希望你明白我的痛点。

你这里有很多困惑。首先也是最重要的一点,委托不是异步委托,而是返回任务的委托。通常会将两者合并,因为通常只从异步操作返回任务,而不必返回。为了满足委托人的要求,您只需使用
Task.FromResult(foo)
,其中
foo
是您最终返回的内容。重要的是,可以同步地满足该返回,因此,如果底层流程是同步的,那么从现在开始根本不需要涉及异步/等待


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

(比较
GetOrCreateAsync
vs
GetOrCreate
)“…该.NET内核必须创建一个状态机…”。不,.NET内核与async和Wait完全无关。是c#编译器完成了这项工作,而不是@VSDekar的运行时可能的副本。在您完成研究后,您应该就@VSDekar提出问题。请查看关于某个主题的现有资源,并尝试自己解决您的问题。@Servy相信我,我已经做了很多研究。对于一种使用了100次的非常特殊的产品,我试图用尽可能准确的措辞回答我的问题。如果我能用一个问题为自己节省几个小时来实现类似的事情,那么我认为值得一试。我所要问的是,是否有人已经对自己解决方案中的
MemoryCache
有所了解。