用 Lambda表示式傳遞委託

iDotNetSpace發表於2009-04-09

在其中用了兩個儲存指標轉換以達到無縫讀取快取,在Cat Chen一語提醒之後,想了一想:的確是沒有必要在快取中使用兩個儲存指標的,其實一個儲存地址,只要保證寫入時在其它執行緒就可以。

更改儲存介質至以下兩個屬性:

namespace CHCache {
    /// 
    /// 快取介質
    /// 
    public class Medium {
        /// 
        /// 儲存區
        /// 
        public object Store { get; set; }
        /// 
        /// 是否正在更新
        /// 
        public bool IsUpdating { get; set; }
    }
}

這裡儲存區用於儲存要快取的實體內容,而IsUpdating則標識其是否正在更新。

對於快取類,則更改了寫入和讀取方式。

/*
 * http://www.cnblogs.com/chsword/
 * chsword
 * Date: 2009-3-31
 * Time: 17:00
 * 
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace CHCache {
    /// 
    /// 雙儲存的類
    /// 
    public class DictionaryCache : IEnumerable {
        /// 
        /// 在此快取構造時初始化字典物件
        /// 
        public DictionaryCache() {
            Store = new Dictionary<string, Medium>();
        }
        public void Add(string key, Func<object> func) {
            if (Store.ContainsKey(key)) {
//修改,如果已經存在,再次新增時則採用其它執行緒 var elem = Store[key]; if (elem.IsUpdating) return;
//正在寫入未命中 var th = new ThreadHelper(elem, func); var td = new Thread(th.Doit); td.Start(); } else {//首次新增時可能也要讀取,所以要本執行緒執行 Console.WriteLine("Begin first write"); Store.Add(key, new Medium { Store = func() }); Console.WriteLine("End first write"); } } /// /// 讀取時所用的索引 /// /// /// public object this[string key] { get { if (!Store.ContainsKey(key)) return null; var elem = Store[key]; return elem.Store; } } Dictionary<string, Medium> Store { get; set; } public IEnumerator GetEnumerator() { return ((IEnumerable)Store).GetEnumerator(); } } }

這裡在新增時只控制了首次寫入快取在主執行緒,而讀取時則直接讀取快取內容。

而執行緒輔助類也進行了簡化,僅將其執行並寫入就好了,丟擲執行緒完全由DictionaryCache控制。

using System;
namespace CHCache {
    /// 
    /// 一個執行緒Helper,用於幫助多丟擲執行緒時傳遞引數
    /// 
    public class ThreadHelper {
        Func<object> Fun { get; set; }
        Medium Medium { get; set; }
        /// 
        /// 通過建構函式來傳遞引數
        /// 
        /// 
        /// 
        public ThreadHelper(Medium m, Func<object> fun) {
            Medium = m;
            Fun = fun;
        }
        /// 
        /// 執行緒入口,ThreadStart委託所對應的方法
        /// 
        public void Doit() {
            Medium.IsUpdating = true;
            Console.WriteLine("Begin write.");
            var ret = Fun.Invoke();
            Medium.Store = ret;
            Console.WriteLine("End write.");
            Medium.IsUpdating = false;
        }
    }
}

其實有的時候思考問題還是不由自主的向著自己的經驗方向刻意安排,這樣通常把問題搞複雜了。

還好有園子裡的朋友幫助,才簡單的解決了問題,這樣的由簡至繁,再由繁衍至簡的過程其實在實際開發中發生的還真不少。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-586875/,如需轉載,請註明出處,否則將追究法律責任。

相關文章