2013-02-28 53 views
0

我有一個方法調用異步方法的await。等待似乎悄然返回

private async void LoadPic(string imageFileName) 
{ 
    StorageFolder sf = Windows.ApplicationModel.Package.Current.InstalledLocation; 
    StorageFolder subFolder = await sf.GetFolderAsync("Assets"); 
    StorageFile sfile = await subFolder.GetFileAsync(imageFileName); 

當我在下一行設置中斷點時,中斷點永遠不會被打中。它只是退出該方法並返回。

public PixelData GrabPixelData(string imageFileName) 
{ 
    if (!ImageDictionary.ContainsKey(imageFileName)) 
    { 
     // doesn't exist yet, so load it 
     LoadPic(imageFileName); 
    } 

    PixelData pd = new PixelData(); 
    bool found = false; 
    while(found == false) { 
     found = ImageDictionary.TryGetValue(imageFileName, out pd); 
    } 
    return pd; 
    // throw new NullReferenceException(); 
} 

我調用LoadPic()後,我添加了一個循環,不斷檢查它是否將此文件中的圖像添加到字典中。它似乎永遠不會被添加,只是掛起。

這種方法在我抽象出來的子類上運行良好。


編輯:

修改有兩件事情。一切似乎現在工作,但是當我將結果分配給子類時,我得到一個空的異常錯誤(即使調試器不指示任何內容爲空!)。

我不知道它是否與包裹在任務中的事實有關。

子類:

private async void LoadPic() 
{ 
    // I realize the async void is to be avoided, but ... I'm not sure because there isn't anything I want it to return. Should it just return a dummy task? 
    sat1.pixelData = await rootPage.GrabPixelData("sat1.png"); 

LoadPic:

 private async Task<PixelData> LoadPic(string imageFileName) 
     { 
      StorageFolder sf = Windows.ApplicationModel.Package.Current.InstalledLocation; 
      StorageFolder subFolder = await sf.GetFolderAsync("Assets"); 
      StorageFile sfile = await subFolder.GetFileAsync(imageFileName); 
... 
      return pd; 

GrabPixelData:

public async Task<PixelData> GrabPixelData(string imageFileName) 
{ 
    if (!ImageDictionary.ContainsKey(imageFileName)) 
    { 
     // doesn't exist yet, so load it 
     PixelData pd = await LoadPic(imageFileName); 
     ImageDictionary.Add(imageFileName, pd); 
    } 

    var test = ImageDictionary[imageFileName]; 

    return ImageDictionary[imageFileName]; 
} 
+0

正如你永遠'await'上'LoadPic',它會回到這裏,繼續的假設下執行,你不需要等待它(因此作爲異步,火和忘記方法調用)。如果那些人返回,我會期望它最終達到你的斷點,但我最近沒有真正使用C#來驗證。 – pickypg 2013-02-28 03:01:12

+0

@pickpg:感謝您對我的思考。如果我在LoadPic上等待,我必須聲明方法異步。異步方法必須返回void或,所以沒有辦法返回我的自定義PixelData類。這在沒有等待LoadPic的子類中起作用。 – micahhoover 2013-02-28 03:06:11

回答

4

你應該避免async void。此外,輪詢共享狀態以檢測異步操作的完成是否定的。這種CPU使用率可能會讓您的應用程序被Windows應用商店拒絕。

我建議你更換LoadPic返回Task<PixelData>。然後將ImageDictionaryDictionary<string, PixelData>更改爲Dictionary<string, Task<PixelData>>。然後,您GrabPixelData方法是這樣的:

public Task<PixelData> GrabPixelData(string imageFileName) 
{ 
    if (!ImageDictionary.ContainsKey(imageFileName)) 
    { 
    // doesn't exist yet, so load it 
    ImageDictionary.Add(imageFileName, LoadPic(imageFileName)); 
    } 

    return ImageDictionary[imageFileName]; 
} 
+0

啊!異步的學習曲線非常高。異步感染它觸及的一切。你必須重新設計一切!我不得不打電話給上面的LoadPic()調用。這至少可以讓它編譯,但是當我嘗試將GrabPixelData(它不爲空)的結果賦值給PixelData對象時,出現空異常。 – micahhoover 2013-02-28 03:31:52

+1

爲了響應你的編輯,返回'async Task'而不是'async void'和'await'返回的'Task'。關於學習曲線,您可能會發現我的[async/await intro](http://blog.stephencleary.com/2012/02/async-and-await.html)有幫助。 – 2013-02-28 04:24:01

+1

@StephenCleary,你的文章很棒,它終於使我的頭吸起了異步的想法並等待着。謝謝! – Snorvarg 2017-06-25 15:06:45