2 Commits

Author SHA1 Message Date
01c2516eaa Fix the symbol cache and image cache 2026-02-22 14:04:44 -05:00
9a7b09ef7c Fix symbol cache 2026-02-22 13:36:28 -05:00
2 changed files with 46 additions and 23 deletions

View File

@@ -57,6 +57,7 @@ namespace PortfolioManager.Cache
{ {
lock (thisLock) lock (thisLock)
{ {
DisposeBitmaps();
imageCache = new Dictionary<ImageType, Bitmap>(); imageCache = new Dictionary<ImageType, Bitmap>();
} }
} }
@@ -66,22 +67,30 @@ namespace PortfolioManager.Cache
lock (thisLock) lock (thisLock)
{ {
if (null == imageCacheInstance) return; if (null == imageCacheInstance) return;
List<Bitmap> bitmaps = imageCache.Values.ToList(); DisposeBitmaps();
foreach (Bitmap bitmap in bitmaps)
{
bitmap.Dispose();
}
imageCache = null; imageCache = null;
imageCacheInstance = null; imageCacheInstance = null;
} }
} }
public IImage GetImage(ImageCache.ImageType imageType) private void DisposeBitmaps()
{ {
lock(this) if(null == imageCache)return;
List<Bitmap> bitmaps = imageCache.Values.ToList();
foreach (Bitmap bitmap in bitmaps)
{ {
return imageCache[imageType]; bitmap.Dispose();
} }
} }
public IImage GetImage(ImageType imageType)
{
lock(thisLock)
{
if (imageCache == null)throw new ObjectDisposedException(nameof(ImageCache));
if (!imageCache.TryGetValue(imageType, out var bitmap))throw new KeyNotFoundException($"Image {imageType} not found in cache.");
return bitmap;
}
}
} }
} }

View File

@@ -10,7 +10,8 @@ namespace PortfolioManager.Cache
public class SymbolCache : IDisposable public class SymbolCache : IDisposable
{ {
private List<String> symbolCache=new List<String>(); private List<String> symbolCache=new List<String>();
private Object thisLock=new Object(); private readonly Object thisLock=new Object();
private readonly Object fetchLock = new Object();
private Thread cacheMonitorThread=null; private Thread cacheMonitorThread=null;
private volatile bool threadRun=true; private volatile bool threadRun=true;
private int cacheRefreshAfter=60000; // Invalidate cache after private int cacheRefreshAfter=60000; // Invalidate cache after
@@ -36,31 +37,42 @@ namespace PortfolioManager.Cache
symbolCache=new List<string>(); symbolCache=new List<string>();
} }
} }
public void Dispose() public void Dispose()
{ {
lock(thisLock) lock(thisLock)
{ {
if(null==symbolCacheInstance || false==threadRun)return; if(null==symbolCacheInstance || false==threadRun)return;
threadRun=false; threadRun=false;
if(null!=cacheMonitorThread)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[SymbolCache:Dispose]Thread state is {0}. Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread)));
cacheMonitorThread.Join(5000);
cacheMonitorThread=null;
MDTrace.WriteLine(LogLevel.DEBUG,"[SymbolCache:Dispose] End.");
}
symbolCacheInstance=null; symbolCacheInstance=null;
} }
if(null!=cacheMonitorThread)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[SymbolCache:Dispose]Thread state is {0}. Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread)));
cacheMonitorThread.Join(5000);
cacheMonitorThread=null;
MDTrace.WriteLine(LogLevel.DEBUG,"[SymbolCache:Dispose] End.");
}
} }
public List<String> GetSymbols() public List<String> GetSymbols()
{ {
lock(this) lock(thisLock)
{ {
if(0==symbolCache.Count)symbolCache=PricingDA.GetSymbols(); if(symbolCache.Count>0)return new List<string>(symbolCache);
return symbolCache; }
lock(fetchLock)
{
List<String> symbols = PricingDA.GetSymbols();
lock(thisLock)
{
if(symbolCache.Count>0)return new List<string>(symbolCache);
symbolCache=new List<String>(symbols);
return new List<string>(symbols);
}
} }
} }
private void ThreadProc() private void ThreadProc()
{ {
int quantums=0; int quantums=0;
@@ -68,16 +80,18 @@ namespace PortfolioManager.Cache
while(threadRun) while(threadRun)
{ {
Thread.Sleep(quantumInterval); Thread.Sleep(quantumInterval);
if(!threadRun)break;
quantums+=quantumInterval; quantums+=quantumInterval;
if(quantums>cacheRefreshAfter) if(quantums>cacheRefreshAfter)
{ {
quantums=0; quantums=0;
List<String> symbols = PricingDA.GetSymbols();
lock(thisLock) lock(thisLock)
{ {
symbolCache=PricingDA.GetSymbols(); symbolCache=new List<string>(symbols);
} }
} }
} }
} }
} }
} }