2012-09-02 28 views
4

我的Windows 8應用程序中應包含一些數據,它只是一些靜態數據。事實上:這是一個簡單的xml文件,應該被反序列化。WinRT:使用GetFileFromApplicationUriAsync()加載靜態數據

數據保存在Assets \ data.xml中(Assets是Blank App Template的默認文件夾)。

我使用這段代碼來訪問它:

private static async Task<MyObject> Load() 
{ 
    if (Windows.ApplicationModel.DesignMode.DesignModeEnabled) 
    { 
     return new SampleData(); 
    } 

    var uri = new Uri("ms-appx:///Assets/data.xml"); 
    Debug.WriteLine("Getting file from Application"); 
    var file = await StorageFile.GetFileFromApplicationUriAsync(uri); 
    Debug.WriteLine("Opening file for reading async"); 
    var stream = await file.OpenStreamForReadAsync(); 

    var serializer = new XmlSerializer(typeof(MyObject)); 

    Debug.WriteLine("Begin deserialization"); 
    var result = (MyObject)serializer.Deserialize(stream.AsInputStream().AsStreamForRead()); 

    return result; 
} 

調用方法:

public static MyObject GetMyObject() 
{ 
    if (_myObject == null) 
    { 
     _myObject = Load().Result; 
    } 

    return _myObject; 
} 

有關的 「滑稽」 的部分是:

如果我設置一個斷點在var uri = new Uri(...);並使用F11逐句通過代碼,一切都按預期工作。我得到所有的調試行,我的應用程序顯示所需的靜態數據。

如果我沒有設置斷點並且不跨越這段代碼,我只能得到Getting a file from Application的調試輸出,沒有更多的事情發生。看起來GetFileFromApplicationUriAsync()永遠不會回來。我等了五分鐘以上,但還沒有發生任何事情。

任何人有任何想法?

+0

你可以發佈一些更多的源代碼嗎?特別是,請從上面的代碼和您如何調用該方法的示例中發佈整個方法。 – Alexander

+0

@Alexander我添加了代碼 –

回答

11

感謝您發佈的代碼。請試着改變你的方法Load如下所示:

//your code 
var file = await StorageFile.GetFileFromApplicationUriAsync(uri).AsTask().ConfigureAwait(false); 
//your code 
var stream = await file.OpenStreamForReadAsync().ConfigureAwait(false); 
//your code 

這裏的主要區別是AsTask()ConfigureAwait(假)

編輯:

很好聽,它的加工。解釋很簡單:當您在GUI線程上使用task.Resulttask.Wait()await關鍵字結合使用時,會導致死鎖。發生這種情況是因爲awaiting代碼在被調用的相同上下文中恢復(在您的情況下 - GUI線程)。並且因爲GUI線程當前正在等待任務完成(通過ResultWait())出現死鎖,並且await之後的代碼將永遠不會被調用。 ConfigureAwait(false)指定可以忽略當前上下文,從而允許您的代碼成功完成。關於此的更多細節:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

+0

似乎工作真的很好!你會如此善良,以改善你的答案,並解釋這到底是什麼?對於第二行更改,您需要刪除'AsTask()'。你可以使用'await file.OpenStreamForReadAsync()。ConfigureAwait(false);' –