緩存筆記
參考黑暗大(Jeffrey)的程式碼C#,轉成VB版
來源: http://blog.darkthread.net/post-2016-04-12-improved-getcachabledata.aspx
CacheManager.vb
Imports System.Runtime.Caching
Namespace GetCachable
Public NotInheritable Class CacheManager
Private Sub New()
End Sub
''' <summary>
''' Lock機能キー
''' </summary>
''' <remarks></remarks>
Private Const AsyncLockPrefix As String = "$$CacheAsyncLock#{0}"
''' <summary>
''' キー名対象取得
''' </summary>
''' <param name="key">キャッシュ名</param>
''' <returns></returns>
Private Shared Function GetAsyncLock(key As String) As Object
Dim cache = MemoryCache.Default
Dim asyncLockKey = String.Format(AsyncLockPrefix, key)
SyncLock cache
If cache(asyncLockKey) Is Nothing Then
cache.Add(asyncLockKey, New Object(), New CacheItemPolicy() With {.SlidingExpiration = New TimeSpan(0, 10, 0)})
End If
End SyncLock
Return cache(asyncLockKey)
End Function
''' <summary>
''' キャッシュデータ取得 (注:非Thread-Safe)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="key">キャッシュ名</param>
''' <param name="callback">コールバック</param>
''' <param name="cacheValue">キャッシュエントリ</param>
''' <param name="forceRefresh">キャッシュをクリアし、検索します</param>
''' <returns></returns>
Private Shared Function GetCachableDataBase(Of T As Class)(key As String,
callback As Func(Of T),
cacheValue As CacheItemPolicy,
forceRefresh As Boolean) As T
Dim cache = MemoryCache.Default
Dim cacheKey = key
SyncLock GetAsyncLock(key)
Dim res = TryCast(cache(cacheKey), T)
If res IsNot Nothing AndAlso forceRefresh Then
cache.Remove(cacheKey)
res = Nothing
End If
If res Is Nothing Then
res = callback()
cache.Add(cacheKey, res, cacheValue)
End If
Return res
End SyncLock
End Function
''' <summary>
''' キャッシュエントリ取得
''' </summary>
''' <param name="cacheValue"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function CreateCacheItemPolicy(cacheValue As Object) As CacheItemPolicy
If TypeOf cacheValue Is DateTimeOffset Then
Return New CacheItemPolicy() With {.AbsoluteExpiration = cacheValue}
ElseIf TypeOf cacheValue Is Integer Then
Return New CacheItemPolicy() With {.SlidingExpiration = New TimeSpan(0, cacheValue, 0)}
Else
Return New CacheItemPolicy() With {.SlidingExpiration = New TimeSpan(0, 10, 0)}
End If
End Function
''' <summary>
''' キャッシュデータ取得 (注:非Thread-Safe)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="key">キャッシュ名</param>
''' <param name="callback">コールバック</param>
''' <param name="cacheMins">保持期間(分)</param>
''' <param name="forceRefresh">キャッシュをクリアし、検索します</param>
''' <returns></returns>
Public Shared Function GetCachableData(Of T As Class)(key As String,
callback As Func(Of T),
cacheMins As Integer,
Optional forceRefresh As Boolean = False) As T
Return GetCachableDataBase(key, callback, CreateCacheItemPolicy(cacheMins), forceRefresh)
End Function
''' <summary>
''' キャッシュデータ取得 (注:非Thread-Safe)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="key">キャッシュ名</param>
''' <param name="callback">コールバック</param>
''' <param name="absExpire">有効期限</param>
''' <param name="forceRefresh">キャッシュをクリアし、検索します</param>
''' <returns></returns>
Public Shared Function GetCachableData(Of T As Class)(key As String,
callback As Func(Of T),
absExpire As DateTimeOffset,
Optional forceRefresh As Boolean = False) As T
Return GetCachableDataBase(key, callback, CreateCacheItemPolicy(absExpire), forceRefresh)
End Function
End Class
End Namespace
Module1.vb
Imports RuntimeCaching.GetCachable
Imports System.Runtime.Caching
Imports System.Threading
Module Module1
Sub Main()
Dim tasks = New List(Of Task)()
For i = 0 To 2
tasks.Add(Task.Factory.StartNew(Function()
Dim data = CacheManager.GetCachableData(Of String)("KEY",
Function()
Console.WriteLine("Thread {0} Start Job", Thread.CurrentThread.ManagedThreadId)
Thread.Sleep(3000)
Console.WriteLine("Thread {0} Stop Job", Thread.CurrentThread.ManagedThreadId)
Return "OK"
End Function,
10)
Return Nothing
End Function))
Next
tasks.ForEach(Sub(t)
t.Wait()
End Sub)
Console.WriteLine("Done")
Console.ReadLine()
End Sub
End Module