在ASP.NET中,如果要讓一個大型物件被所有的request共用,在網站啟動時會先建立,之中會加入lock語法,避免多次重覆建立物件,如果又加上快取機制,那程式碼又會因為加上if-else而變得更亂。好在C#有Lazy類別可以使用,它是Thread-Safe的,以下是示範:

public class LargeObjectManager
{
    public LargeObjectManager() { }
    private static MemoryCache _cache = MemoryCache.Default;

    public DemoClass GetDemoClass()
    {
        var demo1 = new Lazy<DemoClass>(() =>
        {
            // 證明這裡的程式碼只會執行一次,因為 Lazy<T> 會確保只有第一次讀取 Value 時才會執行這段程式碼
            Console.WriteLine("Creating DemoClass instance...");
            return new DemoClass { Name = "Demo1", Description = "This is demo 1", Age = 30 }; 
        });
        CacheItemPolicy policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(10) };   
        var item = _cache.AddOrGetExisting("Demo1", demo1, policy) as Lazy<DemoClass>;
        var existingDemo = item ?? demo1;
        var result = existingDemo.Value;

        return result;
    }
}

然後用Console程式來示範,這邊同時平行執行5個執行緒,看大型物件是不是有重覆產生:

Stack<string> stack = new Stack<string>();
stack.Push("First");
stack.Push("Second");
stack.Push("Third");
stack.Push("Fourth");
stack.Push("Fifth");
Parallel.For(0, 5, i =>
{
    string item = stack.Pop();
    Console.WriteLine($"Popped item: {item}");
    LargeObjectManager largeObjectManager = new LargeObjectManager();
    var result = largeObjectManager.GetDemoClass();
    Console.WriteLine(JsonSerializer.Serialize(result));
});

執行結果: