List<T>
複数のスレッドによって頻繁に読み取られるキャッシュ オブジェクトとしてスタティックがあります。データベースから 5 分ごとにオブジェクトを更新する必要があります。
問題は、オブジェクトがスレッドの 1 つによって使用されている間にオブジェクトを更新すると、foreach
ループが例外をスローすることです。
inUse = true
や などのフラグとinUpdate = true
、フラグが設定または解放されるのを待つwhileループを実装しようとしましたが、最終的には面倒になり、オブジェクトがまったく更新されないバグがあると思います。
このような場合に使えるデザインパターンのようなものはありますか?
編集:
Jim Mischel の exampleに基づいて、次のコードを作成できました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication4
{
class Program
{
static Timer g;
static Timer f;
static Timer r;
static Timer l;
static void Main(string[] args)
{
f=new Timer(
o => SetK(new Random().Next(Int32.MinValue, Int32.MaxValue)),
null, 0, 1);
l=new Timer(
o => SetK(new Random().Next(Int32.MinValue, Int32.MaxValue)),
null, 1, 1);
g=new Timer(o => RunLoop(), null, 1000, Timeout.Infinite);
r=new Timer(o => RunLoop(), null, 1001, Timeout.Infinite);
Console.ReadLine();
}
public static void SetK(int g)
{
try {
if(g<0) {
List<int> k=new List<int>(10);
k.Insert(0, g);
k.Insert(1, g);
k.Insert(2, g);
k.Insert(3, g);
k.Insert(4, g);
k.Insert(5, g);
k.Insert(6, g);
k.Insert(7, g);
k.Insert(8, g);
k.Insert(9, g);
SynchronizedCache<Int32>.Set(k);
}
else {
List<int> k=new List<int>(5);
k.Insert(0, g);
k.Insert(1, g);
k.Insert(2, g);
k.Insert(3, g);
k.Insert(4, g);
SynchronizedCache<Int32>.Set(k);
}
}
catch(Exception e) {
}
}
public static void RunLoop()
{
try {
while(true) {
try {
SynchronizedCache<Int32>.GetLock().EnterReadLock();
foreach(var g in SynchronizedCache<Int32>.Get()) {
Console.Clear();
Console.WriteLine(g);
}
}
finally {
SynchronizedCache<Int32>.GetLock().ExitReadLock();
}
}
}
catch(Exception e) {
}
}
}
public static class SynchronizedCache<T>
{
private static ReaderWriterLockSlim
cacheLock=new ReaderWriterLockSlim();
private static List<T> cache=new List<T>();
public static ReaderWriterLockSlim GetLock()
{
return cacheLock;
}
public static void Set(List<T> list)
{
cacheLock.EnterWriteLock();
try {
cache=list;
}
finally {
cacheLock.ExitWriteLock();
}
}
public static List<T> Get()
{
return cache;
}
}
}