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() 메서드를 호출합니다. 이 메서드는 먼저 캐시 (이 예제에 표시되지 않음)를 찾으면 항목 객체를 반환하거나 그렇지 않으면 웹 서비스 (표시되지 않음)에서 항목 객체를 가져온 다음 캐시에 밀어 넣습니다.

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()의null 참조 예외을 발생시킵니다. tCache가 아직 비동기 작업으로 인해로드/초기화되지 않았기 때문에이 문제가 발생할 수 있습니다.

시도해 보았습니다. obj.tCache = cache.Load()를 기다리고 있습니다. 결과적으로로드가 완료 될 때까지 기다리는데이 발생하지만 응용 프로그램이 중단됩니다. (http://msdn.microsoft.com/en-us/magazine/jj991977.aspx)

여기서 올바른 방향으로 안내해 주시겠습니까? 내 진단이 맞습니까? 그것을 할 수있는 더 좋은 방법이 있습니까? 모든 포인터를 주셔서 감사합니다.

감사합니다.

답변

1

async void이기 때문에 아마도 Initialize을 호출 중이지만 기다리는 중입니다.

public async void Initialize(api obj) 

하려면 :

public async Task Initialize(api obj) 

그런 다음, 당신이 await Initialize(obj)해야합니다 사용하기 전에 해당 캐시의 완료를 보장합니다 당신이해야 할 일은

은 변화이다.

async void은 최상위 이벤트 처리기에만 적용되며 다른 방법으로 사용해서는 안됩니다. 또한 Task.Result 응용 프로그램이 응답하지 않는 이유는 교착 상태를 유발하고 있기 때문에 async 호출간에 동기화 컨텍스트를 마샬링하는 것과 관련되어 있습니다.

+0

감사합니다 !! 그거였다 :) –