2014-12-26 53 views
1

我想在我創建的Windows Phone 8.1 API中實現一個簡單的緩存機制。我在Visual Studio中選擇了Windows Phone可移植類庫模板。在Windows Phone 8.1類庫中實現簡單的緩存

Refrence:http://channel9.msdn.com/Series/Windows-Phone-8-1-Development-for-Absolute-Beginners/Part-22-Storing-and-Retrieving-Serialized-Data

緩存類看起來像這樣,

[DataContract] 
class cache 
{ 
    private const string JSONFILENAME = "data.json"; 

    [DataMember] 
    Dictionary<Int32, item> cDictionary; 

    [DataMember] 
    int _maxSize; 

    public int MaxSize 
    { 
     get { return _maxSize; } 
     set { _maxSize = value; } 
    } 
    public cache(int maxSize){ 
     cDictionary = new Dictionary<int, item>(); 
     _maxSize = maxSize; 
    } 
    public void push(Int32 id, item obj) 
    { 
     if (!cDictionary.ContainsKey(id)) { 
      cDictionary.Add(id, obj); 
     }    
    } 

    internal static async Task<cache> Load() 
    { 
     cache obj = null; 
     try 
     { 
      var jsonSerializer = new DataContractJsonSerializer(typeof(cache)); 

      using (var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(JSONFILENAME)) 
      { 
       obj = (cache)jsonSerializer.ReadObject(myStream); 
      } 
     } 
     catch (FileNotFoundException) 
     { 
      obj = null; 
     } 

     return obj; 
    } 

    internal static async void Save(cache obj) 
    { 
     var serializer = new DataContractJsonSerializer(typeof(cache)); 
     using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
         JSONFILENAME, 
         CreationCollisionOption.ReplaceExisting)) 
     { 
      serializer.WriteObject(stream, obj); 
     } 
    }} 

的項目類,它的對象進入字典是這樣的,

[DataContract] 
class item 
{ 
    [DataMember] 
    string _fName; 

    public string FName 
    { 
     get { return _fName; } 
     set { _fName = value; } 
    } 
    [DataMember] 
    string _lName; 

    public string LName 
    { 
     get { return _lName; } 
     set { _lName = value; } 
    } 
    [DataMember] 
    int _id; 

    public int Id 
    { 
     get { return _id; } 
     set { _id = value; } 
    } 

    public item(int id, string fName, string lName) 
    { 
     this.Id = id; 
     this.FName = fName; 
     this.LName = lName; 
    } 
} 

的想法是:最終用戶創建api的實例並調用方法doSomething()。如果找到該方法,則首先在緩存中查找(在示例中未顯示),返回Item對象,否則從Web服務(未顯示)獲取該項目對象,然後將其推送到緩存。

public class api 
{ 
    cache tCache; 
    string apiKey; 

    public laas(string apiKey) 
    { 
     this.apiKey = apiKey; 
     this.tCache = new cache(100); 
    } 

    public async void Initialize(api obj) 
    { 
     //If cache exists 
     obj.tCache = await cache.Load(); 
     if (obj.tCache == null) 
     { 
      obj.tCache = new cache(100); 
     } 
    } 

    public void doSomething(string id) 
    {    
     tCache.push(id.GetHashCode(),new item(1,"xxxx","xxx")); 
     cache.Save(tCache); 
    } 
} 

我想初始化/加載在API類的構造函數的緩存,但由於ApplicationData.Current.LocalFolder只提供異步方法來讀取和寫入從持久存儲數據,我創建了一個單獨的靜態異步類Initiialize()會加載緩存,因爲製作異步構造函數是沒有意義的。

問題:聲明tCache.push(id.GetHashCode(),新的項目(1, 「XXXX」, 「XXX」));在doSomething()拋出空引用異常。這可能會發生,因爲由於異步操作,tCache尚未被加載/初始化。

我試過obj.tCache = await cache.Load()。結果等待加載完成,但是這會掛起我的應用程序。 (http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

請您在這裏指出正確的方向嗎?我的診斷是正確的嗎?有沒有更好的方法來做到這一點?任何指針讚賞。

謝謝!

回答

1

可能發生的情況是您打電話給Initialize但不等待它,因爲它是async void

你需要做的是改變:

public async void Initialize(api obj) 

要:

public async Task Initialize(api obj) 

然後,你需要await Initialize(obj)這將確保使用之前緩存完成。

請注意,async void僅適用於頂級事件處理程序,不應以其他方式使用。 此外,原因Task.Result掛起你的應用程序是因爲它造成死鎖,這是相關的方式async編組你的呼叫之間的同步上下文。

+0

謝謝!就是這樣:) –