我正在开发一项网络服务,用于从第三方供稿中读取数据,稍微修改并存储,然后将其返回给我的客户。它只需要定期从第三方站点更新。它将作为Azure中的Web角色中的WCF服务运行。
起初我以为我会一直打电话给我的parsefeed方法,但是如果最后一次更新太快就让该调用返回...
public void ParseFeed()
{
if (DateTime.Now > lastrun.AddMinutes(1))
{
//Fetch updated data into something shared here.
//thedata is a public static in Global class
thedata = fetchdata();
lastrun=DateTime.Now;
}
}
但我想,因为抓取可能需要1-2s(它是一个Web服务),多个用户会立即点击该代码。
来自http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312607的由于任何类的静态成员(包括应用程序类)都不是线程安全的,因此用户代码必须提供适当的锁定才能访问静态成员。这适用于您添加到应用程序类的任何静态成员。
我可以使用锁定(不确定如何)编辑:大量信息here
我可以避免静态var并使用缓存,并将我的数据放入其中(但会在到期时删除,多个用户会尝试获取数据)
我可以使用带有虚假数据项的缓存(基本上作为计时器)并在过期时刷新 - 但即使没有人访问该网站,也会刷新。 (也可能不是线程安全的)
我无法真正使用输出缓存,因为客户端以一种可能使每个请求唯一的方式查询我返回的数据:我的服务根据请求进行排序和过滤
BTW我并不担心Azure上多个实例的结果一致性。每个都可以获取自己的,所以我不需要在多个服务器上共享状态。
我觉得有一个简单的解决方案,我完全错过了。想法?
答案 0 :(得分:1)
由于你可能会从缓存中读取的内容比你要写的更多,我会使用ReaderWriterLockSlim来确保多个线程同时读取数据但不能写入。我还要确保缓存的数据是不可变的,以确保消费者不会改变它。
答案 1 :(得分:1)
从您的问题看,它看起来像:
假设这些都是正确的,那么最简单的解决方案就是使用静态变量来存储数据,在整个检查/刷新块周围使用lock
构造。我甚至不愿意尝试做任何聪明的事情,如双重检查锁定模式;锁定争用根本不会成为一个问题,因为与操作Web服务的开销相比,在关键区域花费的时间将变得微不足道,除非它阻塞并且每个人都必须阻止。