快取查詢函式 RuntimeCaching

緩存筆記
參考黑暗大(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