C# 如何在不降低性能的情况下使昂贵的方法数据可用于所有webapi请求

C# 如何在不降低性能的情况下使昂贵的方法数据可用于所有webapi请求,c#,asp.net-web-api2,C#,Asp.net Web Api2,我有一些数据需要在调用WebApi控制器方法后延迟访问(数据由GetModelRelationalInformation()处理)方法,并且可能是一个昂贵的操作,一旦创建该方法,服务的生命周期就存在,服务的其余部分将非常快,但由于传入了其他参数,因此无法缓存结果)。 我希望避免使用完全缓存库或单例,因此认为使用应用程序变量将是前进的方向: if (HttpContext.Current.Application["ModelRelationalInfo"] == null) { Ht

我有一些数据需要在调用WebApi控制器方法后延迟访问(数据由GetModelRelationalInformation()处理)方法,并且可能是一个昂贵的操作,一旦创建该方法,服务的生命周期就存在,服务的其余部分将非常快,但由于传入了其他参数,因此无法缓存结果)。 我希望避免使用完全缓存库或单例,因此认为使用应用程序变量将是前进的方向:

 if (HttpContext.Current.Application["ModelRelationalInfo"] == null)
 {
     HttpContext.Current.Applicatin["ModelRelationalInfo"] = GetModelRelationalInformation();
 }
 return HttpContext.Current.Applicatin["ModelRelationalInfo"];
但是,如果在生成数据之前出现第二个请求,我不希望昂贵的方法再次运行,因此我正在考虑为此添加一个锁,如下所示:

if (HttpContext.Current.Application["ModelRelationalInfo"] == null)
{
    lock (padlock)
    {
        if (HttpContext.Current.Application["ModelRelationalInfo"] == null)
        {
            HttpContext.Current.Applicatin["ModelRelationalInfo"] = GetModelRelationalInformation();
        }
    }
}
return HttpContext.Current.Applicatin["ModelRelationalInfo"];
我知道锁很昂贵,但这只对服务的初始请求(在构建数据时传入的请求)重要。 以这种方式访问应用程序变量安全吗?-是否有其他的方法我们应该考虑,比如独生子更合适?

这是一个更大的服务的一部分,因此将其放入global.asax将增加服务的启动时间,我也希望避免这种情况


编辑:注意,挂锁是一个类成员静态变量,其方法与此代码相同。

我更喜欢使用缓存机制。请看一下System.Web.Caching


对于您的问题,您还可以使用Lazy类。这是此类操作的推荐方式。

注意:如果这应该在代码审查中,我不确定,我不是要求代码审查-这是一个特定的编程问题,但它是一段工作代码,问题确实与最佳实践和设计模式使用有关,在意外情况下的性能和正确性。锁定在这种情况下是必不可少的,但要小心。
padlock
应该是静态的,并且全局可用。@Salar感谢-padlock是一个只读静态变量,存在于该方法所在的类中。您是否测试过并发请求并注意到性能缓慢?如果是这样,请首先尝试在数据库级别优化GetModelRelationalInformation方法(如果适用),然后尝试使用已有的.NET并发集合。另外,如果我没说错的话,缓存在这里没有那么有用,因为参数会更改,缓存可能会增加一些开销。既然一切正常,那么在需要之前不要尝试引入任何可能会增加不必要开销的更改。请看system.web.caching,这有什么好处吗?或者这只是个人偏好?您可以使缓存对象无效或设置过期时间。在某些情况下,它可能比存储在静态对象中要好。缓存对象通常具有弱引用。因此,内存泄漏问题的可能性可能会稍低。当然。在这种情况下,这些数据不是必需的,只需从大量的数据源构建一次,然后混合在一起,直到重新加载服务(可能一年更改几次)后才会过期。