我有一个缓慢且昂贵的方法可以为我返回一些数据:
public Data GetData(){...}
我不想等到这个方法执行。而不是我想立即返回缓存数据。
我有一个类CachedData
,其中包含一个属性Data cachedData
。
所以我想创建另一个方法public CachedData GetCachedData()
,它将启动一个新任务(在其中调用GetData
)并立即返回缓存数据,在任务完成后我们将更新缓存。
我需要线程安全GetCachedData()
,因为我将有多个请求将调用此方法。
我会点亮一下“有什么变化吗?”每分钟,如果它将返回true(cachedData!= currentData),那么我将调用GetCachedData()
。
我是C#
的新人。请帮我实现这个方法。
我正在使用.net framework 4.5.2
答案 0 :(得分:2)
基本理念很明确:
Data
属性,它包含了一个昂贵的函数调用。这似乎是一个直截了当的设计。在某些时候,您可能希望使用事件,但可以在以后添加。
根据具体情况,可能需要对属性进行线程安全访问。我认为如果Data
缓存是一个简单的引用而没有其他数据与它一起更新,则不需要锁定,但是您可能希望声明引用volatile
以便读取线程执行不依赖陈旧的缓存(哈!)版本。 This post似乎有很好的联系来讨论这些问题。
答案 1 :(得分:1)
如果您不会同时调用GetCachedData,则可能无法使用锁定。如果数据为空(肯定是第一次运行),我们将等待很长时间的方法来完成它的工作。
public class SlowClass
{
private static object _lock;
private static Data _cachedData;
public SlowClass()
{
_lock = new object();
}
public void GetCachedData()
{
var task = new Task(DoStuffLongRun);
task.Start();
if (_cachedData == null)
task.Wait();
}
public Data GetData()
{
if (_cachedData == null)
GetCachedData();
return _cachedData;
}
private void DoStuffLongRun()
{
lock (_lock)
{
Console.WriteLine("Locked Entered");
Thread.Sleep(5000);//Do Long Stuff
_cachedData = new Data();
}
}
}
我已在控制台应用程序上测试过。
static void Main(string[] args)
{
var mySlow = new SlowClass();
var mySlow2 = new SlowClass();
mySlow.GetCachedData();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
mySlow.GetData();
mySlow2.GetData();
}
mySlow.GetCachedData();
Console.Read();
}
答案 2 :(得分:-1)
也许你可以使用MemoryCache类, 正如here in MSDN
所解释的那样